/**
	Alumnes: Tomas Gonzalez Sanchez
		 Lluís Hernandez Saladie

	 Compilador de MiniC per Compiladors 2
	---------------------------------------


**/

%{

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "parser.h"
#include "symtab.h"
#include "bo_activacio.h"
#include "c3a_sequence.h"
#include "estructures.h"

#define YYLMAX 100
#define ERROR 99999
#define ARXIU_BA "sortida_blocActi.txt"
#define ARXIU_C3A "sortida_C3a.txt"
#define MAX_ARG 8
#define MAX_INSTR 30


extern FILE *yyout;
 /*FLEX*/
extern int yylineno;
extern int yylex();
extern void yyerror(char*);

 /*SYMTAB*/
sym_scope_id ambit_actual;
int error_sym;
void error_taula_simbols(int codi,const char *lexema);


 /*Auxiliars*/
int line_args;
int * tmp_type_args;

struct llista{
	struct arg * primer;
	struct arg * ultim;
	struct arg * actual;
}ll;

char * name_c3a;
char * name_ba;
char * tmp_lex_args[MAX_ARG];
char * sublexema_act;
int num_args=0;
int return_ctrl=0;

/*int type_found;	*/	/*Ens servira per quan estiguem declarant un tipus en un llistat poguem saber el tipus que es.*/
sym_value_type type_found;	/*El tipus ha tingut que ser modificat per una estructura mes complexa.*/
sym_value_type type_recorded;	/*Estructura auxiliar per la recuperacio d'arguments i tipus de la funcio*/

/* Blocs d'activació*/
int bo_ambit = 0;
activation_bloc ba[2];
int primer=0;

Code_list cl;
char tmp_var[20]; /*emmagatzema el nom de les variables temporals*/
char op_dst[10];
int id_unic = 100;

Tinfo *N;
Tinfo *M;
Tinfo *Q;

int ba_get_type(char *ctipus, int itipus)
{
	
	/*printf("BA ==> tipus que cal reconeixer: %i\n",itipus);*/
 	switch(itipus)
		{
		case INT: strcpy(ctipus, "INT"); break;
		case LONG: strcpy(ctipus, "LONG"); break;
		case UNSIGNED: strcpy(ctipus, "UNSIGNED"); break;
		case FLOAT: strcpy(ctipus, "FLOAT"); break;
		case DOUBLE: strcpy(ctipus, "DOUBLE"); break;
		case VOID: strcpy(ctipus, "VOID"); break;	
		}
	return 0;
}

int ba_new_bloc(char *nom, int tipus, int num_elements)
{
 /*int num_args;*/
 int i;
 struct arg * index;
 Node_ba nba;
 char ctipus[10];
 char nom_sub[20];

	if (primer)
	{ 
	c3a_emet_comen(&cl," ");
	c3a_emet_comen(&cl," ");
	}
	primer=1;


	sprintf(nom_sub,"START %s__%i",nom,id_unic);
    type_found.lexema_c3a = (char *) calloc(strlen(nom)+5,(sizeof(char)));
    sprintf(type_found.lexema_c3a,"%s__%i",nom,id_unic);
	id_unic++;
	c3a_emet_instr(&cl,nom_sub); 
	/*printf("BA ==> New block Activacio %s\n",nom);*/
 	bo_ambit++;
	
 	ba_ini(&ba[bo_ambit]);
	index = ll.primer;

	strcpy(nba.desc,"RETORN");
	nba.posicio = 0;
	nba.mida = 4;
 	ba_new_element(&ba[bo_ambit], nba);
	ba_set_nom(&ba[bo_ambit],nom,tipus);
	ba_Inc_MemLliure(&ba[bo_ambit],4);
    

/* Indica la posició a partir de la qual comencen els parametres l'ambit*/
	ba_set_pos_parameters(&ba[bo_ambit], ba_get_posMem_Lliure(&ba[bo_ambit]));

/*	Tipus de retorn de la funcio*/
	nba.posicio = ba_get_posMem_Lliure(&ba[bo_ambit]);

	ba_get_type(ctipus, tipus);
	/*strcpy(ctipus,"PROVA");*/

	
	strcpy(nba.desc,ctipus); 
 	nba.mida = ba_obtenir_mida((int)index->type);
 	ba_new_element(&ba[bo_ambit], nba);
	ba_Inc_MemLliure(&ba[bo_ambit],nba.mida);

	/*printf("BA ==> num_elem: %i\n",num_elements);*/
	for (i=1;i<=num_elements;i++)
	    	{
			nba.posicio = ba_get_posMem_Lliure(&ba[bo_ambit]);
			strcpy(nba.desc,index->lexema); 
 			nba.mida = ba_obtenir_mida((int)index->type);
 	     	ba_new_element(&ba[bo_ambit], nba);
			ba_Inc_MemLliure(&ba[bo_ambit],nba.mida);
			index = index->next_arg;
	    	}

	strcpy(nba.desc," NONE");
	nba.posicio = ba_get_posMem_Lliure(&ba[bo_ambit]);;
	nba.mida = 8;
 	ba_new_element(&ba[bo_ambit], nba);
	ba_Inc_MemLliure(&ba[bo_ambit],8);


	return(0);
}

int ba_insertar_variable(char *lexema, int type)
{
Node_ba nba;

 	nba.posicio = ba_get_posMem_Lliure(&ba[bo_ambit]);
	strcpy(nba.desc,lexema); 
 	nba.mida = ba_obtenir_mida(type);
 	ba_new_element(&ba[bo_ambit], nba);

	return ba_Inc_MemLliure(&ba[bo_ambit],nba.mida);
 }

int ba_sortir_ambit()
{
	ba_write_out(&ba[bo_ambit], name_ba);
	bo_ambit--;
	return(0);
}


/* C2: Funcions de SUPORT*/
/*Structures Complexes*/
int struct_return_type(char *lexema, char *sublex, int line){
	sym_value_type temporal;
	struct arg * aux;
	int res=ERROR,i=0;
	int args=0;

	ambit_actual=sym_get_scope();
	if(ambit_actual == SYM_ROOT_SCOPE){
		error_sym=sym_global_lookup(lexema,&temporal);
	}else{
		error_sym=sym_lookup(lexema,&temporal);
	}
	if(error_sym == SYMTAB_OK){
		aux=temporal.args;
		args=temporal.args->num_args;
		for(; i< args; i++){
			if(strncmp(aux->lexema, sublex,strlen(sublex))==0){
				res=aux->type;
				break;
			}
			if(i< args-1) aux=aux->next_arg;
		}
		if (res == ERROR){
			fprintf(stderr,"SEMANTICA: %dL - ERROR: Subvariable %s de l'Struct %s no declarada!!!\n",line,lexema,sublex);
			fprintf(yyout,"SEMANTICA: %dL - ERROR: Subvariable %s de l'Struct %s no declarada!!!\n",line,lexema,sublex);
		}
		return res;
	}else{
		fprintf(yyout,"SEMANTICA: %iL - ERROR: Variable Struct %s no declarada!!!\n",line,lexema);
		fprintf(stderr,"SEMANTICA: %dL - ERROR: Variable Struct %s no declarada!!!\n",line,lexema);
		return ERROR;	
	}
}

int composite_return_size(char *lexema,int type,int size, int line){
	struct arg * aux;
	int res=0,i=0;
	int args=0;
    
    if(type == STRUCT){
        aux=ll.primer;
        args=ll.primer->num_args;
        for(; i< args; i++){
            res=ba_obtenir_mida(aux->type)+res;
            aux=aux->next_arg;
        }
    }else{
        res=ba_obtenir_mida(type)*size;
    }
    /*printf("RESULTAT PER == %i ==> %i\n",type,res);*/

    return res;
}



int struct_search_position(char * lexema,char * sublex,int line){
	sym_value_type temporal;
	struct arg * aux;
	int res=ERROR,i=0;
	int args=0;
    int size=0;

	ambit_actual=sym_get_scope();
	if(ambit_actual == SYM_ROOT_SCOPE){
		error_sym=sym_global_lookup(lexema,&temporal);
	}else{
		error_sym=sym_lookup(lexema,&temporal);
	}
	if(error_sym == SYMTAB_OK){
		aux=temporal.args;
		args=temporal.args->num_args;
		for(; i< args; i++){
			if(strncmp(aux->lexema, sublex,strlen(sublex))==0){
				res=size;
				break;
			}else{
                switch(aux->type){
                    case INT:
                        size+=4;
                        break;
                    case FLOAT:
                        size+=8;
                        break;
                    case CHAR:
                        size+=4;
                        break;
                }
            }
			if(i< args-1) aux=aux->next_arg;
		}
        if (res == ERROR){
			fprintf(stderr,"SEMANTICA: %dL - ERROR: Subvariable %s de l'Struct %s no declarada!!!\n",line,lexema,sublex);
			fprintf(yyout,"SEMANTICA: %dL - ERROR: Subvariable %s de l'Struct %s no declarada!!!\n",line,lexema,sublex);
		}
		return res;
	}else{
		fprintf(yyout,"SEMANTICA: %iL - ERROR: Variable Struct %s no declarada!!!\n",line,lexema);
		fprintf(stderr,"SEMANTICA: %dL - ERROR: Variable Struct %s no declarada!!!\n",line,lexema);
		return ERROR;	
	}
}

  /*Funcio que ens comprova els tipus quan es realitza una operacio aritmetica +,-,*,/,% i tambe logiques*/
  /*a més sempre ens mante el tipus que necessitem per una maxima resolucio del resultat de l'operacio*/
int comprova_tipus_op(int type1, int type2, int line){
        /*printf("LOL (%i)   (%i)\n",type1,type2);
        printf("ENTRAREEEEEEEEEEEEEEEEE?????? \n");*/
		if ((type1 == INT || type1 == FLOAT || type1 == INTEGER_CONSTANT || type1 == FLOATING_CONSTANT || type1 == CHAR || type1 == CHARACTER_CONSTANT) &&(type2 == FLOATING_CONSTANT || type2 == FLOAT || type2 == INTEGER_CONSTANT || type2 == INT || type2 == CHAR || type2 == CHARACTER_CONSTANT)){
/*            printf("ENTROOOOOOOOOOOOOOOOOOOOOOOOO\n");*/
			if(type1 == type2){
                switch(type1){
                    case INTEGER_CONSTANT:
                        return INT;
                        break;
                    case FLOATING_CONSTANT:
                        return FLOAT;
                        break;
                    case CHARACTER_CONSTANT:
                        return CHAR;
                        break;
                    default:
                        return type1;
                        break;
                };
			/*Si resulta que son de tipus numerics diferents ho guardarem amb el que te major precisió.*/
			}else if((type1 == INTEGER_CONSTANT && type2 == FLOATING_CONSTANT) || (type1 == FLOATING_CONSTANT && type2 == INTEGER_CONSTANT) || (type1 == INT && type2 == FLOAT)|| (type1 == INT && type2 == FLOATING_CONSTANT)||(type1 == FLOAT && type2 == INT)||(type1 == FLOATING_CONSTANT && type2==INT)|| (type1 == FLOAT && type2 == FLOATING_CONSTANT)||(type1 == FLOATING_CONSTANT ||type2 == FLOAT )){
				return FLOAT;
			}
			else if((type1 == CHARACTER_CONSTANT && type2 ==INTEGER_CONSTANT)||(type1 == INTEGER_CONSTANT && type2 == CHARACTER_CONSTANT) || (type1 == INT && type2 == CHARACTER_CONSTANT) || (type1 == INT && type2 == CHAR) || (type1 == CHARACTER_CONSTANT && type2 == INT) || (type1 == CHAR && type2 == INT)||(type1==INT && type2 == INTEGER_CONSTANT)|| (type1 == INTEGER_CONSTANT && type2 == INT)){
				return INT;
			}
			else if((type1 == CHARACTER_CONSTANT && type2 ==FLOATING_CONSTANT)||(type1 == FLOATING_CONSTANT && type2 == CHARACTER_CONSTANT)|| (type1 == FLOAT && type2 == CHARACTER_CONSTANT) || (type1 == FLOAT && type2 == CHAR) || (type1 == CHARACTER_CONSTANT && type2 == FLOAT) || (type1 == CHAR && type2 == FLOAT)){
				return FLOAT;
			}
			else if((type1 == CHARACTER_CONSTANT && type2 == CHAR)||(type1 == CHAR && type2 == CHARACTER_CONSTANT)){
				return CHAR;
			}
			else{
				fprintf(yyout,"SEMANTICA: %dL - ERROR: Operacio entre Expressions de tipus incompatibles!! (arit)\n",line);
				fprintf(stderr,"SEMANTICA: %dL - ERROR: Operacio entre Expressions de tipus incompatibles!! (arit)\n",line);
				return ERROR;	/* Aqui quin valor li tinc que passar?*/ /*???*/
			}
		}else{
			fprintf(yyout,"SEMANTICA: %dL - ERROR: Operans que no permeten operacions aritmetiques!! (arit)\n",line);
			fprintf(stderr,"SEMANTICA: %dL - ERROR: Operans que no permeten operacions aritmetiques!! (arit)\n",line);
			return ERROR;	/* Aqui quin valor li tinc que passar?*/ /*???*/
		}
}


/*Ens retorna el tipus de la variable passada*/
int tipus_var (char * lexema, int line){
	sym_value_type temporal;

	ambit_actual=sym_get_scope();
	if(ambit_actual == SYM_ROOT_SCOPE){
		error_sym=sym_global_lookup(lexema,&temporal);
	}else{
		error_sym=sym_lookup(lexema,&temporal);
	}
	if(error_sym == SYMTAB_OK){
		type_recorded=temporal;
		return temporal.type;
	}else{
		fprintf(yyout,"SEMANTICA: %iL - ERROR: Variable %s no declarada!!!\n",line,lexema);
		fprintf(stderr,"SEMANTICA: %dL - ERROR: Variable %s no declarada!!!\n",line,lexema);
		return ERROR;	
	}

}

int comprova_tipus_return(int type1, int type2, int line){
		if((type1 == INT && type2 == INTEGER_CONSTANT)|| (type1 == INT && type2 == INT) || (type1 == INT && type2 == CHAR) || (type1 == INT && type2 == CHARACTER_CONSTANT)){
			return type1;
		}
		else if((type1 == FLOAT && type2 == FLOATING_CONSTANT) || (type1 == FLOAT && type2 == FLOAT) || (type1 == FLOAT && type2 == INT)|| (type1 == FLOAT && type2 == INTEGER_CONSTANT) || (type1 == FLOAT && type2 == CHAR) || (type1 == FLOAT && type2 == CHARACTER_CONSTANT)){
			return type1;
		}
		else if((type1 == CHAR && type2 == CHARACTER_CONSTANT)||(type1 == CHAR && type2 == CHAR)|| (type1 == CHAR && type2 == INT) || (type1 == CHAR && type2 == INTEGER_CONSTANT)){
			return type1;
		}
		else if ((type1 == INT && type2 == FLOAT)||(type1 == INT && type2 == FLOATING_CONSTANT)){
			fprintf(yyout,"SEMANTICA: %dL - WARNING: Perdua de precisio en el RETORN!!! (%i - %i)\n",line,type1,type2);
			fprintf(stderr,"SEMANTICA: %dL - WARNING: Perdua de precisio en el RETORN!!!\n",line);
			return type1;
		}else{
			fprintf(yyout,"SEMANTICA: %dL - ERROR: Tipus de retorn!!! (%i - %i)\n",line,type1,type2);
			fprintf(stderr,"SEMANTICA: %dL - ERROR: Tipus de retorn!!!\n",line);
			return ERROR;	/* Aqui quin valor li tinc que passar?*/ /*???*/
		}
}


  /*Funcio que ens comprova els tipus quan s'assignen a una variable*/
  /*Al guardarse en el tipus de la variable, tenim que informar de si es produeix perdua de precisió*/
int comprova_tipus_assign(int type1, int type2, int line){
		if(type1 != ERROR){
			if((type1 == INT && type2 == INTEGER_CONSTANT)|| (type1 == INT && type2 == INT)){
				return type1;
			}
			else if((type1 == FLOAT && type2 == FLOATING_CONSTANT) || (type1 == FLOAT && type2 == FLOAT)){
				return type1;
			}
			else if((type1 == FLOAT && type2 == INTEGER_CONSTANT) || (type1 == FLOAT && type2 == INT)){
				return type1;
			}
			else if((type1 == INT && type2 == FLOATING_CONSTANT) || (type1 == INT && type2 == FLOAT)){
				fprintf(yyout,"SEMANTICA: %dL - WARNING: Assignacio amb perdua de precisió!!\n",line);
				printf("SEMANTICA: %dL - WARNING: Assignacio amb perdua de precisió!!\n",line);
				return type1;
			}
			else if((type1 == INT && type2 == CHARACTER_CONSTANT) || (type1 == INT && type2 == CHAR)){
				return type1;
			}
			else if((type1 == FLOAT && type2 == CHARACTER_CONSTANT) || (type1 == FLOAT && type2 == CHAR)){
				return type1;
			}
			else if((type1 == CHAR && type2 == INTEGER_CONSTANT) || (type1 == CHAR && type2 == INT)){
				return type1;
			}
			else if((type1 == CHAR && type2 == CHAR) || (type2 == CHAR && type2 == CHARACTER_CONSTANT)){
                return type1;
            }
			else if((type1 == CHAR && type2 == FLOATING_CONSTANT) || (type1 == CHAR && type2 == FLOAT)){
				fprintf(yyout,"SEMANTICA: %dL - WARNING: Assignacio amb perdua de precisió!!\n",line);
				printf("SEMANTICA: %dL - WARNING: Assignacio amb perdua de precisió!!\n",line);
				return type1;
			}
			else{
				fprintf(yyout,"SEMANTICA: %dL - ERROR: Assignacio entre Expressions de tipus incompatibles!! (assig)\n",line);
				fprintf(stderr,"SEMANTICA: %dL - ERROR: Assignacio entre Expressions de tipus incompatibles!! (assig)\n",line);
				return ERROR;	/* Aqui quin valor li tinc que passar?*/ /*???*/
			}
		}else{
			return ERROR;
		}
}

 /*Funcio que ens afegeix variables en l'entorn GLOBAL*/
void afegir_var_root(char * lexema, int line){
	error_sym=sym_global_add((const char*)lexema,&type_found);
	if(error_sym!=SYMTAB_OK){
		error_taula_simbols(error_sym,lexema);
	}else{
		fprintf(yyout,"SEMANTICA: %iL - Creada entrada (GLOBAL) per variable => %s (%i)\n",line,lexema,type_found.type);
	}
}

 /*Funcio que afegeix variable en ambit LOCAL*/
void afegir_var_local(char * lexema,int line){
    int pos_m=ba_insertar_variable(lexema,type_found.type);
    type_found.pos_mem=pos_m;
	error_sym=sym_add((const char*)lexema,&type_found);
	error_sym=SYMTAB_OK;
	if(error_sym!=SYMTAB_OK){
		error_taula_simbols(error_sym,lexema);
	}else{
		fprintf(yyout,"SEMANTICA: %iL - Creada entrada (LOCAL) per variable => %s (%i)\n",line,lexema,type_found.type);
	}
}

void afegir_funcio_root(char nom[], int tipus)
{
  struct arg * argument;
 	argument = (struct arg *) malloc(sizeof(struct arg));
	argument->type = tipus;
	argument->lexema = (char *) malloc(sizeof (char)+1);
	strcpy(argument->lexema,"x");
	argument->num_args=1;
	ll.primer = argument;
	ll.ultim = argument;
	ll.actual = ll.primer;
    type_found.type=VOID;
    type_found.lexema_c3a=nom;
	type_found.num_elem = 1;
	type_found.args = ll.primer;
	afegir_var_root(nom,0);
}

/*Funcio per apilar un ambit*/
void push_ambit(char * lexema, int line){
	/*Tenim que guardar l'ambit com a variable amb el tipus per després poder returnar correctament*/
	ambit_actual=sym_get_scope();
	if(ambit_actual == SYM_ROOT_SCOPE){
		fprintf(yyout,"SEMANTICA: %iL - INICIANT EL CANVI D'SCOPE (ambit \"%s\" amb %i arguments)\n",line,lexema,ll.primer->num_args);
		type_found.args=ll.primer;
		afegir_var_root(lexema,line);
		num_args=0;
	}else{
		fprintf(yyout,"SEMANTICA: %iL - ERROR: Intentes especificar una funcio dins una altra!!\n",line);
		fprintf(stderr,"SEMANTICA: %dL - ERROR: Intentes especificar una funcio dins una altra!!\n",line);
	}	
	/*Ara ja podem realitzar el PUSH de l'ambit en el que ens trobavem i canviar al nou ambit.*/
	error_sym=sym_push_scope();
	ambit_actual=sym_get_scope();
	if(error_sym!=SYMTAB_OK){
		error_taula_simbols(error_sym,lexema);
	}else{
		fprintf(yyout,"SEMANTICA: %iL - Apilat el nou ambit per a la funcio \"%s\" amb codi %i\n",line,lexema,ambit_actual);
	}
}



/*Funcio que ens desapila un ambit*/
void pop_ambit(char * lexema){
	ambit_actual=sym_get_scope();
		if(ambit_actual!= SYM_ROOT_SCOPE){
			error_sym=sym_pop_scope();
			if(error_sym==SYMTAB_STACK_UNDERFLOW){
				fprintf(yyout,"SEMANTICA: ERROR: Eliminant l'ambit \"%s\", problemes a la pila!!\n",lexema);
				fprintf(stderr,"SEMANTICA: ERROR: Eliminant l'ambit \"%s\", problemes a la pila!!\n",lexema);
			}else if(error_sym==SYMTAB_NOT_TOP){
				fprintf(yyout,"SEMANTICA: ERROR: Ambit \"%s\" no es troba el cap de la pila, problemes a la pila!!\n",lexema);
				fprintf(stderr,"SEMANTICA: ERROR: Ambit \"%s\" no es troba al cap de la pila, problemes a la pila!!\n",lexema);
			} else {
				if(error_sym!=SYMTAB_OK){
					error_taula_simbols(error_sym,lexema);
				}else{
					fprintf(yyout,"SEMANTICA: -- Desapilant l'ambit \"%s\" amb codi %d\n",lexema,ambit_actual);
				}
			}
		}else{
			fprintf(yyout,"SEMANTICA: ERROR: Intentes desapilar l'ambit arrel!\n");
			fprintf(stderr,"SEMANTICA: ERROR: Intentes desapilar l'ambit arrel!\n");
		}
}


void guardar_arguments_ambit(){
	int i;
	ll.actual=ll.primer;
	for(i=0;i<ll.primer->num_args;i++){
		type_found.type=ll.actual->type;
		afegir_var_local((char *)ll.actual->lexema,line_args);
		ll.actual=ll.actual->next_arg;
	}
	num_args=0;
}

int comprova_tipus_args(){
	int i;
	struct arg * aux;
	
	aux=type_recorded.args;
	for(i=0; i< num_args; i++){
        /*printf("Argument [%i] = %i <== %i\n",i,tmp_type_args[i],aux->type);*/
		if((tmp_type_args[i] != aux->type) &&
		 !((tmp_type_args[i] == INT)&&(aux->type==INT)) &&
		 !((tmp_type_args[i] == FLOAT)&&(aux->type==FLOAT)) &&
		 !((tmp_type_args[i] == CHAR)&&(aux->type==CHAR))){
			return 1;
		}
		if(i!=num_args-1)aux=aux->next_arg;
	}
	return 0;
}


void insert_var(char *lexema,int type, int line){
    int temp;
	ambit_actual=sym_get_scope();
	if(ambit_actual == SYM_ROOT_SCOPE){
		if(type == STRUCT){
			type_found.args=ll.primer;
		}
		afegir_var_root(lexema,line);	
	}
	else{
        temp=type_found.type;
        type_found.type=type;
		afegir_var_local(lexema,line);
        type_found.type=temp;
	}
}

int compara_arguments(char *lexema,int line){
	tipus_var(lexema,0);
	if(type_recorded.args->num_args == num_args){
			if(comprova_tipus_args()==1){
				fprintf(yyout,"SEMANTICA: %iL - ERROR: Parametres passats a la funcio \"%s\" de tipus incorrectes!\n",line,lexema);
				fprintf(stderr,"SEMANTICA: %iL - ERROR: Parametres passat a la funcio \"%s\" de tipus incorrectes!\n",line,lexema);
				return ERROR;
			}
	}else{
		fprintf(yyout,"SEMANTICA: %iL - ERROR: El nombre de parametres ha passar a la funcio \"%s\" %i i se'n passen %i!\n",line,lexema,type_recorded.args->num_args,num_args);
		fprintf(stderr,"SEMANTICA: %iL - ERROR: El nombre de parametres ha passar a la funcio \"%s\" %i i se'n passen %i!\n",line,lexema,type_recorded.args->num_args,num_args);
		return ERROR;
	}
	return 0;
}

char* obtenir_nom_c3a(char * lexema){
   tipus_var(lexema,0);
   return type_recorded.lexema_c3a;
}

int obtenir_num_args(char * lexema){
    tipus_var(lexema,0);
    return type_recorded.args->num_args;
}

int obtenir_tipus_retorn(char * lexema){
    tipus_var(lexema,0);
    return type_recorded.type;
}


%}


%union{		/*Estructura que aprofitem per guardar qualsevol lexema de qualsevol tipus.*/

        struct{	/*El tipus vindrà marcat pel que retorni l'analitzador FLEX, atributs de cada simbol*/
                char *lexema;
                int type;
                int line; /*Mantenim aquest camp tot i tenir el yylineno, per un possible us al futur en l'emmagatzemament del lexema*/
				struct tinfo * info;
        }ident;

	void *no_definit;

}

 /*Definicio de Tokens Terminals pel BISON*/
%token <ident> IDENTIFIER STRING
%token <ident> INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP AND_OP OR_OP 
%token <ident> MUL_ASSIG DIV_ASSIG MOD_ASSIG ADD_ASSIG SUB_ASSIG LEFT_ASSIG 
%token <ident> RIGHT_ASSIG AND_ASSIG XOR_ASSIG OR_ASSIG ELLIPSIS
%token <ident> CHARACTER_CONSTANT INTEGER_CONSTANT FLOATING_CONSTANT

 /*Aquest tokens terminals, forcem l'index per tal d'aprofitar els que tenim a la nostra taula de simbols.*/
%token <ident> SIZEOF 260 TYPE_NAME 282 TYPEDEF 283 EXTERN 284 STATIC 285 AUTO 286
%token <ident> REGISTER 287 CHAR 288 SHORT 289 INT 290 LONG 291 SIGNED 292 
%token <ident> UNSIGNED 293 FLOAT 294 DOUBLE 295 CONST 296 VOLATILE 297 VOID 298
%token <ident> STRUCT 299 UNION 301 ENUM 302 RANGE 303 CASE 304 DEFAULT 305
%token <ident> IF 306 ELSE 307 SWITCH 308 WHILE 309 DO 310 FOR 311 GOTO 312
%token <ident> CONTINUE 313 BREAK 314 RETURN 315 BOOLEAN 316

%type <ident> primary_expression constant postfix_expression unary_expression cast_expression multiplicative_expression additive_expression struct_or_union_specifier struct_or_union shift_expression relational_expression equality_expression AND_expression exclusive_OR_expression inclusive_OR_expression logical_AND_expression logical_OR_expression conditional_expression assignment_expression initializer init_declarator declarator init_declarator_list declaration_specifiers type_specifier expression function_definition jump_statement statement statement_list compound_statement struct_declarator struct_declaration_list struct_declaration struct_declarator_list specifier_qualifier_list parameter_declaration expression_statement Q M

%nonassoc THEN	/* A partir d'un Token no existent a la nostra gramatica del tipus nonassoc definim el desplaçament i així elimiment el conflicte*/
%nonassoc ELSE  /* Informacio trobada a: http://compilers.iecc.com/comparch/article/91-09-030*/



 /*Regles Sintactiques*/
%start program_unit
%%
inicialitzar :/*buida*/{printf("Zona de inicialitzacions\n");
						c3a_reset_line(&cl);	
						ba_reset_out(&ba[bo_ambit], name_ba);
						afegir_funcio_root("PUTL",291);
						afegir_funcio_root("PUTI",290);
						afegir_funcio_root("PUTS",318);
						afegir_funcio_root("PUTC",288);
						afegir_funcio_root("PUTD",295);
						afegir_funcio_root("PUTF",294);
			
						afegir_funcio_root("GETL",291);
						afegir_funcio_root("GETI",290);
						afegir_funcio_root("GETS",318);
						afegir_funcio_root("GETC",288);
						afegir_funcio_root("GETD",295);
						afegir_funcio_root("GETF",294);
}
program_unit : inicialitzar translation_unit
			   {
				c3a_emet_instr(&cl,"HALT");
				/* Guardem variables globals del programa */
				ba_set_nom(&ba[0], "global", 0);
				ba_write_out(&ba[0], name_ba);
				c3a_write_out(&cl,name_c3a);
			   }

primary_expression : IDENTIFIER {
		fprintf(yyout,"GRAMATICA: %dL - primary_expression: IDENTIFIER   <  %s\n",$<ident>1.line,$<ident>1.lexema);
 		$<ident>1.type=tipus_var($<ident>1.lexema,$<ident>1.line);
		$$=$1;
	}
| constant {
		fprintf(yyout,"GRAMATICA: %dL - primary_expression: constant   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		$$=$1;
	}
| STRING {
		fprintf(yyout,"GRAMATICA: %dL - primary_expression: STRING   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		$$=$1;
	}
| '(' expression ')' {
		fprintf(yyout,"GRAMATICA: %dL - primary_expression: (expression)   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		$$=$2;
	}
;
constant : INTEGER_CONSTANT {
		fprintf(yyout,"GRAMATICA: %dL - constant: INTEGER_CONSTANT   <  %s\n",$<ident>1.line,$<ident>1.lexema);$<ident>1.type=INTEGER_CONSTANT;
		char * instr;
        ba_get_temp(&ba[bo_ambit],tmp_var,INT);
		$<ident>$.info = (Tinfo *) calloc(1,sizeof(Tinfo));
		$<ident>$.info->quad=c3a_get_quad(&cl);
		/*sprintf(instr,"%s := %s",tmp_var,$<ident>3.lexema);*/
        instr=(char *) calloc((strlen(tmp_var)+strlen($<ident>1.lexema)+5),sizeof(char));
		sprintf(instr,"%s := %s",tmp_var,$<ident>1.lexema);
		c3a_emet_instr(&cl,instr);
		insert_var(tmp_var,INT,$<ident>1.line);
		/*$$=$1;*/
		strcpy($<ident>$.lexema, tmp_var);
		$<ident>$.type = INT;
	}
| CHARACTER_CONSTANT {
		fprintf(yyout,"GRAMATICA: %dL - constant: CHARACTER_CONSTANT   <  %s\n",$<ident>1.line,$<ident>1.lexema);$<ident>1.type=CHARACTER_CONSTANT;
		/*$$=$1;*/
		char * instr;
        ba_get_temp(&ba[bo_ambit],tmp_var,CHAR);
		/*sprintf(instr,"%s := %s",tmp_var,$<ident>3.lexema);*/
		$<ident>$.info = (Tinfo *) calloc(1,sizeof(Tinfo));
		$<ident>$.info->quad=c3a_get_quad(&cl);
        instr=(char *) calloc((strlen(tmp_var)+strlen($<ident>1.lexema)+5),sizeof(char));
		sprintf(instr,"%s := %s",tmp_var,$<ident>1.lexema);
		c3a_emet_instr(&cl,instr);
		insert_var(tmp_var,CHAR,$<ident>1.line);
		/*$$=$1;*/
		strcpy($<ident>$.lexema, tmp_var);
		$<ident>$.type = CHAR;
	}
| FLOATING_CONSTANT {
		fprintf(yyout,"GRAMATICA: %dL - constant: FLOATING_CONSTANT   <  %s\n",$<ident>1.line,$<ident>1.lexema);$<ident>1.type=FLOATING_CONSTANT;
		/*$$=$1;*/
		char * instr;
        ba_get_temp(&ba[bo_ambit],tmp_var,FLOAT);
		/*sprintf(instr,"%s := %s",tmp_var,$<ident>3.lexema);*/
		$<ident>$.info = (Tinfo *) calloc(1,sizeof(Tinfo));
		$<ident>$.info->quad=c3a_get_quad(&cl);
        instr=(char *) calloc((strlen(tmp_var)+strlen($<ident>1.lexema)+5),sizeof(char));
		sprintf(instr,"%s := %s",tmp_var,$<ident>1.lexema);
		c3a_emet_instr(&cl,instr);
		insert_var(tmp_var,FLOAT,$<ident>1.line);
		/*$$=$1;*/
		strcpy($<ident>$.lexema, tmp_var);
		$<ident>$.type = FLOAT;

	}
;

postfix_expression : primary_expression {
		fprintf(yyout,"GRAMATICA: %dL - postfix_expression: primary_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		$$=$1;
	}
| postfix_expression '[' expression ']' {
        fprintf(yyout,"GRAMATICA: %dL - postfix_expression: postfix_expression [expression]   <  %s\n",$<ident>1.line,$<ident>1.lexema);
        char c[MAX_C3A];
        char variable_temp[MAX_INSTR];

        ba_get_temp(&ba[bo_ambit],tmp_var,$<ident>3.type);
		insert_var(tmp_var,$<ident>3.type,$<ident>1.line);
        sprintf(c,"%s := %i MULTI %s",tmp_var,ba_obtenir_mida($<ident>1.type),$<ident>3.lexema);
        c3a_emet_instr(&cl,c);
        strcpy(variable_temp,tmp_var);

        ba_get_temp(&ba[bo_ambit],tmp_var,$<ident>1.type);
		insert_var(tmp_var,$<ident>1.type,$<ident>1.line);
        sprintf(c,"%s := %s[%s]",tmp_var,$<ident>1.lexema,variable_temp);
        c3a_emet_instr(&cl,c);

        strcpy(variable_temp,tmp_var);
        $<ident>$.lexema=variable_temp;
        $<ident>$.type=$<ident>1.type;
        }
| postfix_expression '(' ')' {
		fprintf(yyout,"GRAMATICA: %dL - postfix_expression: postfix_expression ()   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	}
| postfix_expression '(' argument_expression_list ')' {
        char c[MAX_C3A];
        int tipus;
		fprintf(yyout,"GRAMATICA: %dL - postfix_expression: (argument_expression_list)   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		compara_arguments($<ident>1.lexema,$<ident>1.line);
        tipus=obtenir_tipus_retorn($<ident>1.lexema);
        if(tipus==VOID){
            sprintf(c,"CALL %s, %i",obtenir_nom_c3a($<ident>1.lexema),obtenir_num_args($<ident>1.lexema));
            $<ident>$.info = (Tinfo *) calloc(1,sizeof(Tinfo));
            $<ident>$.info->quad = c3a_get_quad(&cl);
            }
        else{
			ba_get_temp(&ba[bo_ambit],tmp_var, tipus);
			insert_var(tmp_var,tipus,$<ident>1.line);
            sprintf(c,"%s := CALL %s, %i",tmp_var,obtenir_nom_c3a($<ident>1.lexema),obtenir_num_args($<ident>1.lexema));
            $<ident>$.lexema=tmp_var;
            /*printf("PUJAREM ==> %s\n",$<ident>$.lexema);*/
            $<ident>$.type=tipus;
            $<ident>$.info = (Tinfo *) calloc(1,sizeof(Tinfo));
            $<ident>$.info->quad = c3a_get_quad(&cl);
        }
        c3a_emet_instr(&cl,c);
	}
| postfix_expression '.' IDENTIFIER {
		int i = ERROR;
        int des;
        char c[MAX_C3A];

		fprintf(yyout,"GRAMATICA: %dL - postfix_expression: postfix_expression '.' IDENTIFIER   <  %s - %s\n",$<ident>1.line,$<ident>1.lexema, $<ident>3.lexema);

        des=struct_search_position($<ident>1.lexema,$<ident>3.lexema,$<ident>3.line);
		i=struct_return_type($<ident>1.lexema,$<ident>3.lexema,$<ident>3.line);
		if (i != ERROR){
            ba_get_temp(&ba[bo_ambit],tmp_var, i);
    		insert_var(tmp_var,i,$<ident>1.line);
            sprintf(c,"%s := %s[%i]",tmp_var,$<ident>1.lexema,des);
            c3a_emet_instr(&cl,c);

            $<ident>$.lexema=(char *) malloc(sizeof(strlen(tmp_var)+1));
            strcpy($<ident>$.lexema,tmp_var);
			$<ident>$.type=i;
			$<ident>$.line=$<ident>1.line; 
		}
	}
| postfix_expression INC_OP {
        fprintf(yyout,"GRAMATICA: %dL - postfix_expression: primary_expression   INC_OP <  %s\n",$<ident>1.line,$<ident>1.lexema);
   		int tipus;
        char instr[MAX_C3A];
        
        $<ident>$.info = (Tinfo *) calloc(1,sizeof(Tinfo));
        $<ident>$.info->quad = c3a_get_quad(&cl);

		tipus = $<ident>1.type;
		ba_get_temp(&ba[bo_ambit],tmp_var, tipus);
        ba_get_binary_op("+",op_dst,tipus);
		c3a_emet_binari(&cl,tmp_var,op_dst, $<ident>1.lexema,"1");

        sprintf(instr,"%s := %s",$<ident>1.lexema,tmp_var);
        c3a_emet_instr(&cl,instr);

		$<ident>$.type=tipus;
		$<ident>$.line=$<ident>2.line;
        insert_var(tmp_var,tipus,$<ident>1.line);
        $<ident>$.lexema=(char *) malloc(sizeof(strlen(tmp_var)+1));
        strcpy($<ident>$.lexema,tmp_var);
        
        }
| postfix_expression DEC_OP {
        fprintf(yyout,"GRAMATICA: %dL - postfix_expression: primary_expression   DEC_OP <  %s\n",$<ident>1.line,$<ident>1.lexema);
   		int tipus;
        char instr[MAX_C3A];
        
        $<ident>$.info = (Tinfo *) calloc(1,sizeof(Tinfo));
        $<ident>$.info->quad = c3a_get_quad(&cl);

		tipus = $<ident>1.type;
		ba_get_temp(&ba[bo_ambit],tmp_var, tipus);
        ba_get_binary_op("-",op_dst,tipus);
		c3a_emet_binari(&cl,tmp_var,op_dst, $<ident>1.lexema,"1");

        sprintf(instr,"%s := %s",$<ident>1.lexema,tmp_var);
        c3a_emet_instr(&cl,instr);

		$<ident>$.type=tipus;
		$<ident>$.line=$<ident>2.line;
        insert_var(tmp_var,tipus,$<ident>1.line);
        $<ident>$.lexema=(char *) malloc(sizeof(strlen(tmp_var)+1));
        strcpy($<ident>$.lexema,tmp_var);
        }
;

argument_expression_list : assignment_expression {
		int tmp_types[MAX_ARG];
        char instr[MAX_C3A];
		fprintf(yyout,"GRAMATICA: %dL - argument_expression_list: assignment_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		if($<ident>1.type == INTEGER_CONSTANT || $<ident>1.type == FLOATING_CONSTANT ||$<ident>1.type == CHARACTER_CONSTANT){
			tmp_types[num_args]=$<ident>1.type; 
		}else{
			tmp_types[num_args]=tipus_var($<ident>1.lexema,$<ident>1.line); 
		}
        sprintf(instr,"PARAM %s",$<ident>1.lexema);
        c3a_emet_instr(&cl,instr);
		tmp_type_args=tmp_types;
		num_args++;
	}
| argument_expression_list ',' assignment_expression {
		int tmp_types[MAX_ARG];
		int i;
        char instr[MAX_C3A];
		fprintf(yyout,"GRAMATICA: %dL - argument_expression_list: argument_expression_list , assignment_expression   <  %s - %s\n",$<ident>1.line,$<ident>1.lexema,$<ident>3.lexema);
		for(i=0;i<num_args;i++) tmp_types[i]=tmp_type_args[i];
		if($<ident>3.type == INTEGER_CONSTANT || $<ident>3.type == FLOATING_CONSTANT ||$<ident>3.type == CHARACTER_CONSTANT){
			tmp_types[num_args]=$<ident>3.type; 
		}else{
			tmp_types[num_args]=tipus_var($<ident>3.lexema,$<ident>3.line); 
		}
        sprintf(instr,"PARAM %s",$<ident>3.lexema);
        c3a_emet_instr(&cl,instr);
		num_args++;
	}
;
unary_expression : postfix_expression {
		fprintf(yyout,"GRAMATICA: %dL - unary_expression: postfix_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		$$=$1;
	}
| INC_OP unary_expression {fprintf(yyout,"GRAMATICA: %dL - unary_expression: INC_OP unary_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| DEC_OP unary_expression {fprintf(yyout,"GRAMATICA: %dL - unary_expression: DEC_OP unary_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| unary_operator cast_expression {
        fprintf(yyout,"GRAMATICA: %dL - unary_expression: unary_operator cast_expression   <  %s(%s)\n",$<ident>1.line,$<ident>1.lexema,$<ident>2.lexema);
		ba_get_temp(&ba[bo_ambit],tmp_var, $<ident>2.type);
		ba_get_unary_op($<ident>1.lexema,op_dst,$<ident>2.type);
		c3a_emet_unari(&cl,op_dst,$<ident>2.lexema, tmp_var);

		$<ident>$.lexema=(char *) calloc(strlen(tmp_var)+1,sizeof(char));
		sprintf($<ident>$.lexema,"%s",tmp_var);
		$<ident>$.type = $<ident>2.type;
        insert_var(tmp_var,$<ident>2.type,$<ident>1.line);

		$<ident>$.info = (Tinfo *) calloc(1, sizeof(Tinfo));
		$<ident>$.info->lls = (Tlist *) calloc(1, sizeof(Tlist));
		$<ident>$.info->llc = (Tlist *) calloc(1, sizeof(Tlist));

		c3a_insert_list ($<ident>$.info->llc, c3a_get_quad(&cl));

		
		c3a_emet_instr(&cl,"GOTO ");
		/*insert_var($<ident>2.lexema,$<ident>2.type, $<ident>2.line);*/
		/*MANOLO*/
        }
| SIZEOF unary_expression {fprintf(yyout,"GRAMATICA: %dL - unary_expression: SIZEOF unary_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| SIZEOF '(' type_name ')' {fprintf(yyout,"GRAMATICA: %dL - unary_expression: SIZEOF (type_name)   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;

unary_operator : '&' {fprintf(yyout,"GRAMATICA: %dL - unary_operator: &   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| '*' {
        fprintf(yyout,"GRAMATICA: %dL - unary_operator: *   <  %s\n",$<ident>1.line,$<ident>1.lexema);
        $<ident>$.lexema="*";
        }
| '+' {
        fprintf(yyout,"GRAMATICA: %dL - unary_operator: +   <  %s\n",$<ident>1.line,$<ident>1.lexema);
        $<ident>$.lexema="+";
        }
| '-' {fprintf(yyout,"GRAMATICA: %dL - unary_operator: -   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		$<ident>$.lexema ="-";}
| '~' {
        fprintf(yyout,"GRAMATICA: %dL - unary_operator: ~   <  %s\n",$<ident>1.line,$<ident>1.lexema);
        $<ident>$.lexema="~";
        }
| '!' {
        fprintf(yyout,"GRAMATICA: %dL - unary_operator: !   <  %s\n",$<ident>1.line,$<ident>1.lexema);
        $<ident>$.lexema="!";
        }
;

cast_expression : unary_expression {
		fprintf(yyout,"GRAMATICA: %dL - cast_expression: unary_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		$$=$1;
	}
| '(' type_name ')' cast_expression {
            fprintf(yyout,"GRAMATICA: %dL - cast_expression: (type_name) cast_expression   <  (%s)%s\n",$<ident>1.line,$<ident>2.lexema,$<ident>4.lexema);
            if(($<ident>2.type != $<ident>4.type)&& $<ident>2.type != ERROR && $<ident>4.type){
                ba_get_temp(&ba[bo_ambit],tmp_var, $<ident>2.type);
                ba_get_unary_cast(op_dst,$<ident>4.type,$<ident>2.type);
                c3a_emet_unari(&cl,op_dst,$<ident>4.lexema, tmp_var);

                $<ident>$.type=$<ident>2.type;
                $<ident>$.lexema=(char*) calloc(strlen(tmp_var)+1,sizeof(char));
                sprintf($<ident>$.lexema,"%s",tmp_var);
                insert_var(tmp_var,$<ident>2.type,$<ident>1.line);
            }else{
                $$=$<ident>4;
            }
        }
;

 /*Aqui tindrem que controlar els tipus que realitzin l'operació (ho tenim que anar pujant)*/
multiplicative_expression :  cast_expression {
			fprintf(yyout,"GRAMATICA: %dL - multiplicative_expression:  cast_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
			$$=$1;}
| multiplicative_expression  '*' cast_expression {
			fprintf(yyout,"GRAMATICA: %dL - multiplicative_expression: multiplicative_expression * cast_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
			int tipus;
            char temporal[20];

			sprintf(temporal,"%s",$<ident>3.lexema);
			tipus = comprova_tipus_op($<ident>1.type,$<ident>3.type,$<ident>1.line);
			ba_get_temp(&ba[bo_ambit],tmp_var, tipus);
			ba_get_binary_op("*",op_dst,tipus);
			c3a_emet_binari(&cl,tmp_var,op_dst, $<ident>1.lexema,temporal);

			$<ident>$.type=tipus;
			$<ident>$.line=$<ident>3.line;
            insert_var(tmp_var,tipus,$<ident>1.line);
            $<ident>$.lexema=(char *) malloc(sizeof(strlen(tmp_var)+1));
			strcpy($<ident>$.lexema,tmp_var);
		}
| multiplicative_expression  '/' cast_expression {
		fprintf(yyout,"GRAMATICA: %dL - multiplicative_expression: multiplicative_expression / cast_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);

			int tipus;
            char temporal[20];

			sprintf(temporal,"%s",$<ident>3.lexema);
			tipus = comprova_tipus_op($<ident>1.type,$<ident>3.type,$<ident>1.line);
			ba_get_temp(&ba[bo_ambit],tmp_var, tipus);
			ba_get_binary_op("/",op_dst,tipus);
			c3a_emet_binari(&cl,tmp_var,op_dst, $<ident>1.lexema,temporal);


			$<ident>$.type=tipus;
			$<ident>$.line=$<ident>3.line;
            insert_var(tmp_var,tipus,$<ident>1.line);
            $<ident>$.lexema=(char *) malloc(sizeof(strlen(tmp_var)+1));
			strcpy($<ident>$.lexema,tmp_var);
		}
| multiplicative_expression  '%' cast_expression {
		fprintf(yyout,"GRAMATICA: %dL - multiplicative_expression: multiplicative_expression %% cast_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
			int tipus;
            char temporal[20];

			sprintf(temporal,"%s",$<ident>3.lexema);
			tipus = comprova_tipus_op($<ident>1.type,$<ident>3.type,$<ident>1.line);
			ba_get_temp(&ba[bo_ambit],tmp_var, tipus);
			ba_get_binary_op("%",op_dst,tipus);
			c3a_emet_binari(&cl,tmp_var,op_dst, $<ident>1.lexema,temporal);


			$<ident>$.type=tipus;
			$<ident>$.line=$<ident>3.line;
            insert_var(tmp_var,tipus,$<ident>1.line);
            $<ident>$.lexema=(char *) malloc(sizeof(strlen(tmp_var)+1));
			strcpy($<ident>$.lexema,tmp_var);
		}
;

 /*Aqui es on tindrem que controlar els tipus que realitzin l'operació (ho tenim que anar pujant)*/
additive_expression : multiplicative_expression {
			fprintf(yyout,"GRAMATICA: %dL - additive_expression: multiplicative_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema); 
			$$=$1;
		}
| additive_expression '+' multiplicative_expression {
			fprintf(yyout,"GRAMATICA: %dL - additive_expression: additive_expression + multiplicative_expression   <  %s+%s\n",$<ident>1.line,$<ident>1.lexema,$<ident>3.lexema);
			int tipus;
            char temporal[20];

			sprintf(temporal,"%s",$<ident>3.lexema);
			
			tipus = comprova_tipus_op($<ident>1.type,$<ident>3.type,$<ident>1.line);
			ba_get_temp(&ba[bo_ambit],tmp_var, tipus);
			/*printf("EI que el tipus de la suma es: %i\n", tipus);*/
			ba_get_binary_op("+",op_dst,tipus);
			c3a_emet_binari(&cl,tmp_var,op_dst, $<ident>1.lexema,temporal);

			$<ident>$.type=tipus;
			$<ident>$.line=$<ident>3.line;
            insert_var(tmp_var,tipus,$<ident>1.line);
            $<ident>$.lexema=(char *) malloc(sizeof(strlen(tmp_var)+1));
			strcpy($<ident>$.lexema,tmp_var);
		}
| additive_expression '-' multiplicative_expression {
			fprintf(yyout,"GRAMATICA: %dL - additive_expression: additive_expression - multiplicative_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);

			int tipus;
            char temporal[20];

			sprintf(temporal,"%s",$<ident>3.lexema);
			tipus = comprova_tipus_op($<ident>1.type,$<ident>3.type,$<ident>1.line);
			ba_get_temp(&ba[bo_ambit],tmp_var, tipus);
			ba_get_binary_op("-",op_dst,tipus);
			c3a_emet_binari(&cl,tmp_var,op_dst, $<ident>1.lexema,temporal);

            /*printf("----> %i\n",tipus);*/
			$<ident>$.type=tipus;
			$<ident>$.line=$<ident>3.line;
            insert_var(tmp_var,tipus,$<ident>1.line);
            $<ident>$.lexema=(char *) malloc(sizeof(strlen(tmp_var)+1));
			strcpy($<ident>$.lexema,tmp_var);
		}
;

shift_expression : additive_expression {
			fprintf(yyout,"GRAMATICA: %dL - shift_expression: additive_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema); 
			$$=$1;
		}
| shift_expression LEFT_OP additive_expression {fprintf(yyout,"GRAMATICA: %dL - shift_expression: shift_expression LEFT_OP additive_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| shift_expression RIGHT_OP additive_expression {fprintf(yyout,"GRAMATICA: %dL - shift_expression: shift_expression RIGHT_OP additive_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;

relational_expression : shift_expression {
		fprintf(yyout,"GRAMATICA: %dL - relational_expression: shift_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema); 
		$$=$1;
		/*printf("Relational expression %s\n",$<ident>$.lexema);*/
	}
| relational_expression '<' shift_expression {
        fprintf(yyout,"GRAMATICA: %dL - relational_expression: relational_expression < shift_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
            char c[MAX_C3A];
			char instr[MAX_C3A];
			int quad;
			int lin;
	

            ba_get_temp(&ba[bo_ambit],tmp_var,$<ident>3.type);
            insert_var(tmp_var,$<ident>3.type,$<ident>1.line);
            sprintf(c,"%s := %s LT%c %s",tmp_var,$<ident>1.lexema,get_leter_type($<ident>1.type),$<ident>3.lexema);
			quad = c3a_get_quad(&cl);
			
            c3a_emet_instr(&cl,c); 

			$<ident>$.lexema = (char *) calloc(strlen(tmp_var)+1,sizeof(char));
			strcpy($<ident>$.lexema,tmp_var);
            $<ident>$.info = (Tinfo *)calloc(1,sizeof(Tinfo));
            $<ident>$.info -> llc = (Tlist *) calloc(1,sizeof(Tlist));
            $<ident>$.info -> llf = (Tlist *) calloc(1,sizeof(Tlist));

			quad = c3a_get_quad(&cl);
			$<ident>$.info->quad=quad;
			c3a_insert_list($<ident>$.info->llc,quad);
			sprintf(instr,"IF %s GOTO ",tmp_var);
			
			lin=c3a_emet_instr(&cl, instr);
			c3a_insert_list($<ident>$.info->llf,quad+1);
			strcpy(instr,"GOTO ");
			lin=c3a_emet_instr(&cl,instr);
        }
| relational_expression '>' shift_expression {
        fprintf(yyout,"GRAMATICA: %dL - relational_expression: relational_expression > shift_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
            char c[MAX_C3A];
			char instr[MAX_C3A];
			int quad;
			int lin;
	

            ba_get_temp(&ba[bo_ambit],tmp_var,$<ident>3.type);
            insert_var(tmp_var,$<ident>3.type,$<ident>1.line);
            sprintf(c,"%s := %s GT%c %s",tmp_var,$<ident>1.lexema,get_leter_type($<ident>1.type),$<ident>3.lexema);
			quad = c3a_get_quad(&cl);
			
            c3a_emet_instr(&cl,c); 

			$<ident>$.lexema = (char *) calloc(strlen(tmp_var)+1,sizeof(char));
			strcpy($<ident>$.lexema,tmp_var);
            $<ident>$.info = (Tinfo *)calloc(1,sizeof(Tinfo));
            $<ident>$.info -> llc = (Tlist *) calloc(1,sizeof(Tlist));
            $<ident>$.info -> llf = (Tlist *) calloc(1,sizeof(Tlist));

			quad = c3a_get_quad(&cl);
			$<ident>$.info->quad=quad;
			c3a_insert_list($<ident>$.info->llc,quad);
			sprintf(instr,"IF %s GOTO ",tmp_var);
			
			lin=c3a_emet_instr(&cl, instr);
			c3a_insert_list($<ident>$.info->llf,quad+1);
			strcpy(instr,"GOTO ");
			lin=c3a_emet_instr(&cl,instr);


        }
| relational_expression LE_OP shift_expression {
        fprintf(yyout,"GRAMATICA: %dL - relational_expression: relational_expression LE_OP shift_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
            char c[MAX_C3A];
			char instr[MAX_C3A];
			int quad;
			int lin;
	

            ba_get_temp(&ba[bo_ambit],tmp_var,$<ident>3.type);
            insert_var(tmp_var,$<ident>3.type,$<ident>1.line);
            sprintf(c,"%s := %s LE%c %s",tmp_var,$<ident>1.lexema,get_leter_type($<ident>1.type),$<ident>3.lexema);
			quad = c3a_get_quad(&cl);
			
            c3a_emet_instr(&cl,c); 

			$<ident>$.lexema = (char *) calloc(strlen(tmp_var)+1,sizeof(char));
			strcpy($<ident>$.lexema,tmp_var);
            $<ident>$.info = (Tinfo *)calloc(1,sizeof(Tinfo));
            $<ident>$.info -> llc = (Tlist *) calloc(1,sizeof(Tlist));
            $<ident>$.info -> llf = (Tlist *) calloc(1,sizeof(Tlist));

			quad = c3a_get_quad(&cl);
			$<ident>$.info->quad=quad;
			c3a_insert_list($<ident>$.info->llc,quad);
			sprintf(instr,"IF %s GOTO ",tmp_var);
			
			lin=c3a_emet_instr(&cl, instr);
			c3a_insert_list($<ident>$.info->llf,quad+1);
			strcpy(instr,"GOTO ");
			lin=c3a_emet_instr(&cl,instr);
        }
| relational_expression GE_OP shift_expression {
        fprintf(yyout,"GRAMATICA: %dL - relational_expression: relational_expression GE_OP shift_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
            char c[MAX_C3A];
			char instr[MAX_C3A];
			int quad;
			int lin;
	
            ba_get_temp(&ba[bo_ambit],tmp_var,$<ident>3.type);
            insert_var(tmp_var,$<ident>3.type,$<ident>1.line);
            sprintf(c,"%s := %s GE%c %s",tmp_var,$<ident>1.lexema,get_leter_type($<ident>1.type),$<ident>3.lexema);
			quad = c3a_get_quad(&cl);
			
            c3a_emet_instr(&cl,c); 

			$<ident>$.lexema = (char *) calloc(strlen(tmp_var)+1,sizeof(char));
			strcpy($<ident>$.lexema,tmp_var);
            $<ident>$.info = (Tinfo *)calloc(1,sizeof(Tinfo));
            $<ident>$.info -> llc = (Tlist *) calloc(1,sizeof(Tlist));
            $<ident>$.info -> llf = (Tlist *) calloc(1,sizeof(Tlist));

			quad = c3a_get_quad(&cl);
			$<ident>$.info->quad=quad;
			c3a_insert_list($<ident>$.info->llc,quad);
			sprintf(instr,"IF %s GOTO ",tmp_var);
			
			lin=c3a_emet_instr(&cl, instr);
			c3a_insert_list($<ident>$.info->llf,quad+1);
			strcpy(instr,"GOTO ");
			lin=c3a_emet_instr(&cl,instr);
        }
;

equality_expression : relational_expression {
		fprintf(yyout,"GRAMATICA: %dL - equality_expression: relational_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema); 
		$$=$1;
	}
| equality_expression EQ_OP relational_expression {
            char c[MAX_C3A];
			char instr[MAX_C3A];
			int quad;
			int lin;
			
			fprintf(yyout,"GRAMATICA: %dL - equality_expression: equality_expression EQ_OP relational_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
            ba_get_temp(&ba[bo_ambit],tmp_var,$<ident>3.type);
            insert_var(tmp_var,$<ident>3.type,$<ident>1.line);
            sprintf(c,"%s := %s EQ %s",tmp_var,$<ident>1.lexema,$<ident>3.lexema);
			quad = c3a_get_quad(&cl);
			
            c3a_emet_instr(&cl,c); 

			$<ident>$.lexema = (char *) calloc(strlen(tmp_var)+1,sizeof(char));
			strcpy($<ident>$.lexema,tmp_var);
            $<ident>$.info = (Tinfo *)calloc(1,sizeof(Tinfo));
            $<ident>$.info -> llc = (Tlist *) calloc(1,sizeof(Tlist));
            $<ident>$.info -> llf = (Tlist *) calloc(1,sizeof(Tlist));

			quad = c3a_get_quad(&cl);
			$<ident>$.info->quad=quad;
			c3a_insert_list($<ident>$.info->llc,quad);
			sprintf(instr,"IF %s GOTO ",tmp_var);
			
			lin=c3a_emet_instr(&cl, instr);
			c3a_insert_list($<ident>$.info->llf,quad+1);
			strcpy(instr,"GOTO ");
			lin=c3a_emet_instr(&cl,instr);
            }
| equality_expression NE_OP relational_expression {
            char c[MAX_C3A];
			char instr[MAX_C3A];
			int quad;
			int lin;
	
            fprintf(yyout,"GRAMATICA: %dL - equality_expression: equality_expression NE_OP relational_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);

            ba_get_temp(&ba[bo_ambit],tmp_var,$<ident>3.type);
            insert_var(tmp_var,$<ident>3.type,$<ident>1.line);
            sprintf(c,"%s := %s NE %s",tmp_var,$<ident>1.lexema,$<ident>3.lexema);
			quad = c3a_get_quad(&cl);
			
            c3a_emet_instr(&cl,c); 

			$<ident>$.lexema = (char *) calloc(strlen(tmp_var)+1,sizeof(char));
			strcpy($<ident>$.lexema,tmp_var);

            $<ident>$.info = (Tinfo *)calloc(1,sizeof(Tinfo));
            $<ident>$.info -> llc = (Tlist *) calloc(1,sizeof(Tlist));
            $<ident>$.info -> llf = (Tlist *) calloc(1,sizeof(Tlist));
			quad = c3a_get_quad(&cl);
			$<ident>$.info->quad=quad;
			c3a_insert_list($<ident>$.info->llc,quad);
			sprintf(instr,"IF %s GOTO ",tmp_var);
			
			lin=c3a_emet_instr(&cl, instr);
			c3a_insert_list($<ident>$.info->llf,quad+1);
			strcpy(instr,"GOTO ");
			lin=c3a_emet_instr(&cl,instr);
            }
;

AND_expression : equality_expression {
		fprintf(yyout,"GRAMATICA: %dL - AND_expression: equality_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		$$=$1;
	}
| AND_expression '&' equality_expression {fprintf(yyout,"GRAMATICA: %dL - AND_expression: AND_expression & equality_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;

exclusive_OR_expression : AND_expression {
		fprintf(yyout,"GRAMATICA: %dL - exclusive_OR_expression: AND_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema); 
		$$=$1;
	}
| exclusive_OR_expression '^' AND_expression {
            fprintf(yyout,"GRAMATICA: %dL - exclusive_OR_expression: exclusive_OR_expresion ^ AND_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
            }
;

inclusive_OR_expression : exclusive_OR_expression {
		fprintf(yyout,"GRAMATICA: %dL - inclusive_OR_expression: exclusive_OR_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema); 
		$$=$1;
	}
| inclusive_OR_expression '|' exclusive_OR_expression {
		fprintf(yyout,"GRAMATICA: %dL - inclusive_OR_expression: exclusive_OR_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	}
;

logical_AND_expression : inclusive_OR_expression {
		fprintf(yyout,"GRAMATICA: %dL - logical_AND_expression: inclusive_OR_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema); 
		$$=$1;
	}
| logical_AND_expression AND_OP inclusive_OR_expression {
		int num;
		int i;

		fprintf(yyout,"GRAMATICA: %dL - logical_AND_expression: logical_AND_expression AND_OP inclusive_OR_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
        /*$$=$2;
        c3a_fusionar_list($<ident>$.info->llf,$<ident>1.info->llf);*/
        $$=$1;
        /* ????? Que es lo de COMPLETA?????? */

/*		$<ident>$.type=comprova_tipus_op($<ident>1.type,$<ident>3.type,$<ident>3.line);*/

		if (($<ident>$.info->llf == NULL) && ($<ident>3.info->llf !=NULL)) { 
				$<ident>$.info->llf = (Tlist *) calloc(1,sizeof(Tlist));
			    c3a_fusionar_list($<ident>$.info->llf,$<ident>3.info->llf);}
		else if (($<ident>$.info->llf != NULL) &&($<ident>3.info->llf != NULL))
			{  c3a_fusionar_list($<ident>$.info->llf,$<ident>3.info->llf);}

		num = c3a_get_elements($<ident>1.info->llc);

		for (i=0;i<num;i++)
			{   c3a_back_patching(&cl,c3a_get_elemAt($<ident>1.info->llc,i),$<ident>3.info->quad);}

		$<ident>$.info->llc = $<ident>3.info->llc;
	}
;

logical_OR_expression : logical_AND_expression {
		fprintf(yyout,"GRAMATICA: %dL - logical_OR_expression: logical_AND_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema); 
		$$=$1;
	}
| logical_OR_expression OR_OP logical_AND_expression {
		int i;
		int num;
		int quad;

		fprintf(yyout,"GRAMATICA: %dL - logical_OR_expression: logical_OR_expression OR_OP logicl_AND_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
        $$=$1;



		if (($<ident>$.info->llc == NULL) && ($<ident>3.info->llc !=NULL)) { 
				$<ident>$.info->llc = (Tlist *) calloc(1,sizeof(Tlist));
			    c3a_fusionar_list($<ident>$.info->llc,$<ident>3.info->llc);}
		else if (($<ident>$.info->llc != NULL) &&($<ident>3.info->llc != NULL))
			{  c3a_fusionar_list($<ident>$.info->llc,$<ident>3.info->llc);}


		printf("Expressions amb OR ==> quad %i\n",quad);
		num = c3a_get_elements($<ident>1.info->llf);

		for (i=0;i<num;i++)
			{   printf("Expressions amb OR posicions de salt fals %i\n",c3a_get_elemAt($<ident>1.info->llf,i));
				c3a_back_patching(&cl,c3a_get_elemAt($<ident>1.info->llf,i),$<ident>3.info->quad);}

		$<ident>$.info->llf = $<ident>3.info->llf;
	}
;

conditional_expression : logical_OR_expression {
		fprintf(yyout,"GRAMATICA: %dL - conditional_expression: logical_OR_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema); 
		$$=$1;
	}
| logical_OR_expression '?' expression ':' conditional_expression {fprintf(yyout,"GRAMATICA: %dL - conditional_expression: logical_OR_expression ? expression : conditional_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;

assignment_expression : conditional_expression {
		fprintf(yyout,"GRAMATICA: %dL - assignment_expression: conditional_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema); 
		$$=$1;
	}
| unary_expression assignment_operator assignment_expression {
		char * instr;

		fprintf(yyout,"GRAMATICA: %dL - assignment_expression: unary_expression assignment_operator assignment_expression   <  %s := %s\n",$<ident>1.line,$<ident>1.lexema,$<ident>3.lexema);
		if ($<ident>3.info == NULL){
			$<ident>$.info = (Tinfo *) calloc(1,sizeof(Tinfo));
			$<ident>$.info->quad = c3a_get_quad(&cl);
		}else{
			$<ident>$.info = $<ident>3.info;
			printf(" Assignment => %i\n",$<ident>$.info->quad);
		}		
		$<ident>$.type=comprova_tipus_assign($<ident>1.type,$<ident>3.type,$<ident>3.line);
		$<ident>$.line=$<ident>2.line;
        instr = (char*) calloc((strlen($<ident>1.lexema)+strlen($<ident>3.lexema)+5),sizeof(char));
		sprintf(instr,"%s := %s", $<ident>1.lexema,$<ident>3.lexema);
		c3a_emet_instr( &cl,instr);

	}
;

assignment_operator : '=' {fprintf(yyout,"GRAMATICA: %dL - assignment_operator: =   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| MUL_ASSIG {fprintf(yyout,"GRAMATICA: %dL - assignment_operator: MUL_ASSIG   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| DIV_ASSIG {fprintf(yyout,"GRAMATICA: %dL - assignment_operator: DIV_ASSIG   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| MOD_ASSIG {fprintf(yyout,"GRAMATICA: %dL - assignment_operator: MOD_ASSIG   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| ADD_ASSIG {fprintf(yyout,"GRAMATICA: %dL - assignment_operator: ADD_ASSIG   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| SUB_ASSIG {fprintf(yyout,"GRAMATICA: %dL - assignment_operator: SUB_ASSIG   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| LEFT_ASSIG {fprintf(yyout,"GRAMATICA: %dL - assignment_operator: LEFT_ASSIG   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| RIGHT_ASSIG {fprintf(yyout,"GRAMATICA: %dL - assignment_operator: RIGHT_ASSIG   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| AND_ASSIG {fprintf(yyout,"GRAMATICA: %dL - assignment_operator: AND_ASSIG   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| XOR_ASSIG {fprintf(yyout,"GRAMATICA: %dL - assignment_operator: XOR_ASSIG   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| OR_ASSIG {fprintf(yyout,"GRAMATICA: %dL - assignment_operator: OR_ASSIG   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| error {yyerrok;}			/*TRACTAMENT D'ERROR SINTACTIC*/
;

expression : assignment_expression {
    $$=$1;
    fprintf(yyout,"GRAMATICA: %dL - expression: assignment_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
    }
| expression ',' assignment_expression {
    $$=$3;
    fprintf(yyout,"GRAMATICA: %dL - expression: expression , assignment_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);
    }
;

 /*Si int i; o int i=0; entra aqui*/
declaration : declaration_specifiers ';' {fprintf(yyout,"GRAMATICA: %dL - declaration: declaration_specifiers   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| declaration_specifiers init_declarator_list ';' {
		fprintf(yyout,"GRAMATICA: %dL - declaration: declaration_specifiers init_declarator_list   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	}
;

 /* Per si tenim per exemple UNSIGNED INT tenim que controlar que pot haver-hi un llistat*/
declaration_specifiers : type_specifier {
		fprintf(yyout,"GRAMATICA: %dL - declaration_specifiers: type_specifier (%i)  <  %s\n",$<ident>1.line,$<ident>1.type,$<ident>1.lexema);
		type_found.type=$<ident>1.type;
		$$=$1;
	}
| type_specifier declaration_specifiers {
		fprintf(yyout,"GRAMATICA: %dL - declaration_specifiers: type_specifier declaration_specifiers   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		type_found.type=$<ident>1.type;
	}
;

init_declarator_list : init_declarator {
		fprintf(yyout,"GRAMATICA: %dL - init_declarator_list: init_declarator   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		$$=$1;
	}
| init_declarator_list ',' init_declarator {fprintf(yyout,"GRAMATICA: %dL - init_declarator_list: init_declarator_list , init_declarator   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		$$=$1;
	}
;


 /* Inicialització de variables*/
init_declarator : declarator {
            int ts=0;
			Node_ba nba;
			fprintf(yyout,"GRAMATICA: %dL - init_declarator: declarator   <  %s\n",$<ident>1.line,$<ident>1.lexema);
			ambit_actual=sym_get_scope();
			if(ambit_actual == SYM_ROOT_SCOPE){
				if($<ident>1.type == STRUCT){
                    ts= composite_return_size($<ident>1.lexema,$<ident>1.type,0,$<ident>1.line);
                    type_found.total_size=(int * ) malloc(sizeof(int));
                    *type_found.total_size= ts;
					type_found.args=ll.primer;
				}
                if(type_found.total_size == NULL){
                    ts =  ba_obtenir_mida($<ident>1.type);
                    type_found.total_size=(int * ) malloc(sizeof(int));
                    *type_found.total_size =ts;
                    }
				afegir_var_root($<ident>1.lexema,$<ident>1.line);
				nba.posicio =  ba_get_posMem_Lliure(&ba[bo_ambit]);
				strcpy(nba.desc, $<ident>1.lexema);
				nba.mida =(int)* type_found.total_size;
				ba_new_element(&ba[bo_ambit],nba);
				ba_Inc_MemLliure(&ba[bo_ambit],nba.mida);	
			}
			else{
				/*printf(" %s (%d)\n",$<ident>1.lexema,$<ident>1.type);*/
				afegir_var_local($<ident>1.lexema,$<ident>1.line);
			}
			$$=$1;
			if($<ident>1.type == STRUCT) num_args=0;
            type_found.total_size=NULL;
		}
| declarator '=' initializer {
			Node_ba nba;
			fprintf(yyout,"GRAMATICA: %dL - init_declarator: declarator = initializer   <  %s\n",$<ident>1.line,$<ident>1.lexema);
			ambit_actual=sym_get_scope();
			if(ambit_actual == SYM_ROOT_SCOPE){
				afegir_var_root($<ident>1.lexema,$<ident>1.line);	
				nba.posicio =  ba_get_posMem_Lliure(&ba[bo_ambit]);
				strcpy(nba.desc, $<ident>1.lexema);
				nba.mida = ba_obtenir_mida((int)$<ident>1.type);
				ba_new_element(&ba[bo_ambit],nba);
				ba_Inc_MemLliure(&ba[bo_ambit],nba.mida);
			}
			else{
				/*printf(" === %s (%d)\n",$<ident>1.lexema,$<ident>1.type);*/
				afegir_var_local($<ident>1.lexema,$<ident>1.line);
			}
			$$=$3; 
		}
| error {yyerrok;yyclearin;}			/*TRACTAMENT D'ERROR SINTACTIC*/
;


 /*Tipus de retorn de les funcions i de les variables*/
type_specifier : VOID {
	fprintf(yyout,"GRAMATICA: %dL - type_specifier: VOID   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	$<ident>$.type=VOID;
	$<ident>$.line=$<ident>1.line;
	type_found.type=VOID;
	}
| CHAR {
	fprintf(yyout,"GRAMATICA: %dL - type_specifier: CHAR   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	$<ident>$.type=CHAR;
	$<ident>$.line=$<ident>1.line;
	type_found.type=CHAR;
	}
| SHORT {
	fprintf(yyout,"GRAMATICA: %dL - type_specifier: SHORT   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	$<ident>$.type=SHORT;
	$<ident>$.line=$<ident>1.line;
	type_found.type=SHORT;
	}
| INT {
	fprintf(yyout,"GRAMATICA: %dL - type_specifier: INT   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	$<ident>$.type=INT;
	$<ident>$.line=$<ident>1.line;
	type_found.type=INT;
	}
| LONG {
	fprintf(yyout,"GRAMATICA: %dL - type_specifier: LONG   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	$<ident>$.type=LONG;
	$<ident>$.line=$<ident>1.line;
	type_found.type=LONG;
	}
| FLOAT {
	fprintf(yyout,"GRAMATICA: %dL - type_specifier: FLOAT   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	$<ident>$.type=FLOAT;
	$<ident>$.line=$<ident>1.line;
	type_found.type=FLOAT;
	}
| DOUBLE {
	fprintf(yyout,"GRAMATICA: %dL - type_specifier: DOUBLE   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	$<ident>$.type=DOUBLE;
	$<ident>$.line=$<ident>1.line;
	type_found.type=DOUBLE;
	}
| SIGNED {
	fprintf(yyout,"GRAMATICA: %dL - type_specifier: SIGNED   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	$<ident>$.type=SIGNED;
	$<ident>$.line=$<ident>1.line;
	type_found.type=SIGNED;
	}
| UNSIGNED {
	fprintf(yyout,"GRAMATICA: %dL - type_specifier: UNSIGNED   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	$<ident>$.type=UNSIGNED;
	$<ident>$.line=$<ident>1.line;
	type_found.type=UNSIGNED;
	}
	/*A VEURE COM HO PASSA AIXO*/
| struct_or_union_specifier {
	fprintf(yyout,"GRAMATICA: %dL - type_specifier: struct_or_union_specifier   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	$$=$1;
	}
;

struct_or_union_specifier : struct_or_union IDENTIFIER '{' struct_declaration_list '}' {
		fprintf(yyout,"GRAMATICA: %dL - struct_or_union_specifier: struct_or_union IDENTIFIER {struct_declaration_list}   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		$$=$1;
	}
| struct_or_union '{' struct_declaration_list '}' {
            
            fprintf(yyout,"GRAMATICA: %dL - struct_or_union_specifier: struct_or_union {struct_declaration_list}   <  %s\n",$<ident>1.line,$<ident>1.lexema);

    }
| struct_or_union IDENTIFIER {fprintf(yyout,"GRAMATICA: %dL - struct_or_union_specifier: struct_or_union IDENTIFIER   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;

struct_or_union : STRUCT {
		fprintf(yyout,"GRAMATICA: %dL - struct_or_union: STRUCT   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		$<ident>$.type=STRUCT;
	}
| UNION {
		fprintf(yyout,"GRAMATICA: %dL - struct_or_union: UNION   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		$<ident>$.type=UNION;
	}
;

struct_declaration_list : struct_declaration {
		fprintf(yyout,"GRAMATICA: %dL - struct_declaration_list: struct_declaration   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	}
| struct_declaration_list struct_declaration {
		fprintf(yyout,"GRAMATICA: %dL - struct_declaration_list: struct_desclaration_list struct_declaration   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	}
;

struct_declaration : specifier_qualifier_list struct_declarator_list ';' {
		fprintf(yyout,"GRAMATICA: %dL - struct_declration: specifier_qualifier_list struct_declarator_list;   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		$$=$2;
		}
;

/*Control de la declaració dels elements d'un struct*/
struct_declarator_list : struct_declarator {
			fprintf(yyout,"GRAMATICA: %dL - struct_declarator_list: struct_declarator   <  %s(%d)\n",$<ident>1.line,$<ident>1.lexema,$<ident>1.type);
			$$=$1;
		}
| struct_declarator_list ',' struct_declarator {
		fprintf(yyout,"GRAMATICA: %dL - struct_declarator_list: struct_declarator_list , struct_declarator   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		$$=$3;
		}
;

struct_declarator : declarator {
			fprintf(yyout,"GRAMATICA: %dL - struct_declarator: declarator   <  %s(%d)\n",$<ident>1.line,$<ident>1.lexema,$<ident>1.type);
			$$=$1;

			struct arg * element;
			element = (struct arg *) malloc(sizeof(struct arg));
			element->type=$<ident>1.type;
			element->lexema=(char *) malloc(strlen($<ident>1.lexema)+1);
			element->lexema=$<ident>1.lexema;
			if(num_args==0){
				ll.primer= element;
				ll.ultim= element;
				ll.actual=ll.primer;
			}else{
				ll.ultim->next_arg=element;
				ll.ultim= element;
			}

			ll.primer->num_args = ++num_args;
		}
| ':' conditional_expression {fprintf(yyout,"GRAMATICA: %dL - struct_declarator: _:_ conditional_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| declarator ':' conditional_expression {fprintf(yyout,"GRAMATICA: %dL - struct_declarator: declarator _:_ conditional_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;

 /*Tipus de declaracions: Identifficador, arguments, argument_if, array, llista de parametres, llista identificadors, def_funcio buida*/
declarator : IDENTIFIER {
		fprintf(yyout,"GRAMATICA: %dL - declarator: IDENTIFIER   <  %s(%d)\n",$<ident>1.line,$<ident>1.lexema,type_found.type);
		$<ident>1.type=type_found.type;
		$$=$1;
	}
| '(' declarator ')' {
		fprintf(yyout,"GRAMATICA: %dL - declarator: (declarator)   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		$$=$2;
	}
| declarator '[' conditional_expression ']' {
        int ts=0;
        ts= composite_return_size($<ident>1.lexema,$<ident>1.type,atoi($<ident>3.lexema),$<ident>3.line);
        type_found.total_size=(int * ) malloc(sizeof(int));
        *type_found.total_size=ts;
        fprintf(yyout,"GRAMATICA: %dL - declarator: declarator [conditional_expression]   <  %s\n",$<ident>1.line,$<ident>1.lexema);}		/*Això quan hi ha un IF?*/
| declarator '[' ']' {fprintf(yyout,"GRAMATICA: %dL - declarator: declarator []   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
 /*Quan una funcio ha sigut declarada i es cridada des de una altra, ex: res=calcul(variable);*/
| declarator '(' identifier_list ')' {fprintf(yyout,"GRAMATICA: %dL - declarator: declarator(identifier_list)   <  %s\n",$<ident>1.line,$<ident>1.lexema);}

 /*Aquestos hem d'introduir un nou ambit(scope) a la pila SYMTAB*/
 /*declarator (parameter_type_list) es l'inici del control de parametres*/
| declarator '(' parameter_type_list ')' {
		fprintf(yyout,"GRAMATICA: %dL - declarator: declarator(parameter_type_list)   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		type_found.type=$<ident>1.type;
		type_found.num_elem=ll.primer->num_args;
		
		ba_new_bloc($<ident>1.lexema, $<ident>1.type,type_found.num_elem);
		push_ambit($<ident>1.lexema,$<ident>1.line); 
		line_args=$<ident>1.line;
		guardar_arguments_ambit();
	}
| declarator '(' ')' {		
		struct arg * argument;
		argument = (struct arg *) malloc(sizeof(struct arg));

		ll.primer= argument;
		ll.ultim= argument;
		ll.actual=ll.primer;

		ll.primer->num_args=0;
		type_found.num_elem=0;
		fprintf(yyout,"GRAMATICA: %dL - declarator: declarator ()   <  %s\n",$<ident>1.line,$<ident>1.lexema) ;
		
		$<ident>1.type=type_found.type;
		ba_new_bloc($<ident>1.lexema, $<ident>1.type,type_found.num_elem);
		push_ambit($<ident>1.lexema,$<ident>1.line); 
		$$=$1;
	}
;

/*Retorna la llista de paramtres, tenim que controlar i afegir-los a l'ambit*/
parameter_type_list : parameter_list {fprintf(yyout,"GRAMATICA: %dL - parameter_type_list: parameter_list   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| parameter_list ',' ELLIPSIS {fprintf(yyout,"GRAMATICA: %dL - parameter_type_list: parameter_list , ELLIPSIS   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;

/*Separacio del parametres un a un per ','*/
parameter_list : parameter_declaration {
		fprintf(yyout,"GRAMATICA: %dL - parameter_list: parameter_declaration   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		}
| parameter_list ',' parameter_declaration {fprintf(yyout,"GRAMATICA: %dL - parameter_list: parameter_list , parameter_declaration   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;


 /*Parametres declarats a cada funcio: tipus variable, tipus abstracte, tipus tipus variable (unsigned int var) */
parameter_declaration : declaration_specifiers declarator {

		struct arg * argument;
		argument = (struct arg *) malloc(sizeof(struct arg));

		argument->type=$<ident>1.type;
		argument->lexema=(char *) malloc(strlen($<ident>2.lexema)+1);
		argument->lexema=$<ident>2.lexema;

		if(num_args==0){
			ll.primer= argument;
			ll.ultim= argument;
			ll.actual=ll.primer;
		}else{
			ll.ultim->next_arg=argument;
			ll.ultim= argument;
		}

		ll.primer->num_args = ++num_args;
		fprintf(yyout,"GRAMATICA: %dL - parameter_declaration: declaration_specifiers declarator   <  %s - %s\n",$<ident>1.line,$<ident>1.lexema,$<ident>2.lexema);
	}
| declaration_specifiers abstract_declarator {fprintf(yyout,"GRAMATICA: %dL - parameter_declaration: declaration_specifiers abstract_declarator   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| declaration_specifiers {
	struct arg * argument;
	fprintf(yyout,"GRAMATICA: %dL - parameter_declaration: declaration_specifiers   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	
	argument = (struct arg *) malloc(sizeof(struct arg));
	ll.primer= argument;
	ll.ultim= argument;
	ll.actual=ll.primer;
	ll.primer->num_args=0;
	$$=$1;
	}
;

identifier_list : IDENTIFIER {fprintf(yyout,"GRAMATICA: %dL - identifier_list: IDENTIFIER   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| identifier_list ',' IDENTIFIER {fprintf(yyout,"GRAMATICA: %dL - identifier_list: identifier_list , IDENTIFIER   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;

type_name : specifier_qualifier_list {fprintf(yyout,"GRAMATICA: %dL - type_name: specifier_qualifier_list   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| specifier_qualifier_list abstract_declarator {fprintf(yyout,"GRAMATICA: %dL - type_name: specifier_qualifier_list abstract_declarator   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;

specifier_qualifier_list : type_specifier specifier_qualifier_list {
	fprintf(yyout,"GRAMATICA: %dL - type_specifier specifier_qualifier_list   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	$$=$1
	}
| type_specifier {
	fprintf(yyout,"GRAMATICA: %dL - type_specifier   <  %s(%d)\n",$<ident>1.line,$<ident>1.lexema,$<ident>1.type);
	$$=$1;
	}
;


abstract_declarator : '(' abstract_declarator ')' {fprintf(yyout,"GRAMATICA: %dL - abstract_declarator: (abstract_declarator)   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| '[' ']' {fprintf(yyout,"GRAMATICA: %dL - abstract_declarator: []   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| '[' conditional_expression ']' {fprintf(yyout,"GRAMATICA: %dL - abstract_declarator: [conditional_expression]   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| abstract_declarator '[' ']' {fprintf(yyout,"GRAMATICA: %dL - abstract_declarator: abstract_declarator []   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| abstract_declarator '[' conditional_expression ']' {fprintf(yyout,"GRAMATICA: %dL - abstract_declarator: abstract_declarator [conditional_expression]   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| '(' ')' {fprintf(yyout,"GRAMATICA: %dL - abstract_declarator: ()   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| '(' parameter_type_list ')' {fprintf(yyout,"GRAMATICA: %dL - abstract_declarator: (parameter_type_list)   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| abstract_declarator '(' ')' {fprintf(yyout,"GRAMATICA: %dL - abstract_declarator: abstract_declarator()   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| abstract_declarator '(' parameter_type_list ')' {fprintf(yyout,"GRAMATICA: %dL - abstract_declarator: abstract_declarator (paramteter_type_list)   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;

initializer : assignment_expression {fprintf(yyout,"GRAMATICA: %dL - initializer: assignment_expression   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| '{' initializer_list '}' {fprintf(yyout,"GRAMATICA: %dL - initializer: {initializer_list}   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| '{' initializer_list ',' '}' {fprintf(yyout,"GRAMATICA: %dL - initializer: {initializer ,}   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;

initializer_list : initializer {
			fprintf(yyout,"GRAMATICA: %dL - initializer_list: initializer   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| initializer_list ',' initializer {fprintf(yyout,"GRAMATICA: %dL - initializer_list: initializer_list , initializer   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;

statement : labeled_statement {fprintf(yyout,"GRAMATICA: %dL - statement: labeled_statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| compound_statement {
		fprintf(yyout,"GRAMATICA: %dL - statement: compound_statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		if($<ident>1.info == NULL){
			printf("NO PUJA LA LLISTA\n");
		}else{
			printf("SIIIIIIIIIIIIIIIIIIII    %s\n",$<ident>1.lexema);
		}
		}
| expression_statement {
		/*printf("Aixo redueix a statement %s\n",$<ident>$.lexema);*/
        $$=$1;
        if($<ident>$.info->lls != NULL){
            printf("------ expression_statement: VAIG PUJANT\n");
        }else{
            printf("------ expression_statement: NO VAIG PUJANT\n");
        }
        Tlist * t;
        t= (Tlist *) calloc(1,sizeof(Tlist));
        if ($<ident>$.info == NULL)
        {
            printf("Genero la primera llista ==> %s\n",$<ident>1.lexema);
            $<ident>$.info = (Tinfo *) calloc(1,sizeof(Tinfo));
            $<ident>$.info->lls = (Tlist *) calloc (1, sizeof(Tlist)); 
            c3a_insert_list($<ident>$.info->lls,c3a_get_quad(&cl));
        }
        else
        {
            printf("Afegeixo a la llista el QUAD actual ==> %s\n",$<ident>1.lexema);
            if ($<ident>$.info->lls == NULL) 
            {
                printf("NO HI A RES\n");
                $<ident>$.info->lls = (Tlist *) calloc(1,sizeof(Tlist));
                }
            else printf("SI QUE HI HA ALGO\n");    
            /*c3a_insert_list($<ident>$.info->lls,c3a_get_quad(&cl));*/
            c3a_insert_list(t,c3a_get_quad(&cl));
            $<ident>$.info->lls = t;
        }
		fprintf(yyout,"GRAMATICA: %dL - statement: expression_statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| selection_statement {
		/*printf("Valor del punter: %i\n",$<ident>1.info->lls);*/
		fprintf(yyout,"GRAMATICA: %dL - statement: selection_statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| iteration_statement {fprintf(yyout,"GRAMATICA: %dL - statement: iteration_statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| jump_statement {fprintf(yyout,"GRAMATICA: %dL - statement: jump_statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);$$=$1}
;
M_switch : /*buida*/ { M = (Tinfo *)calloc(1,sizeof(Tinfo));
					   M->quad = c3a_get_quad(&cl);}

labeled_statement : IDENTIFIER ':' statement {fprintf(yyout,"GRAMATICA: %dL - labeled_statement: IDENTIFIER : statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| CASE conditional_expression ':' M_switch statement {
			fprintf(yyout,"GRAMATICA: %dL - labeled_statement: CASE conditional_expression: statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| DEFAULT ':' M_switch statement {
			fprintf(yyout,"GRAMATICA: %dL - labeled_statement: DEFAULT : statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;

compound_statement : '{' '}' {fprintf(yyout,"GRAMATICA: %dL - compound_statement: {}   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| '{' declaration_list '}' {fprintf(yyout,"GRAMATICA: %dL - compound_statement: {declaration_list}   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| '{' statement_list '}' {
		fprintf(yyout,"GRAMATICA: %dL - compound_statement: {statement_list}   <  %s\n",$<ident>1.line,$<ident>2.lexema);
		$$=$2;
		/*printf("Compound : %i\n",$<ident>2.info->quad);*/
	}
| '{' declaration_list statement_list '}' {
		fprintf(yyout,"GRAMATICA: %dL - compound_statement: {declaration_list statement_list}   <  %s\n",$<ident>1.line,$<ident>3.lexema);
		$$=$3;
	}
;

statement_list : statement {
					    $$=$1;
						printf("Linia inserida com a final ==> %i\n",c3a_get_quad(&cl));
						fprintf(yyout,"GRAMATICA: %dL - statement_list: statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| statement_list statement {
            Tinfo * S1;
            Tinfo * S2;

            S1=$<ident>1.info;
            S2=$<ident>2.info;
            fprintf(yyout,"GRAMATICA: %dL - statement_list: statement_list statement   <  %s, %s\n",$<ident>1.line,$<ident>1.lexema,$<ident>2.lexema);
            if($<ident>1.info == NULL){
                printf("EL CAMP INFO DE $1 es NULL\n");
                $$ = $2;
            }else{
                printf("EL CAMP INFO $1 Fine =>> %s\n",$<ident>1.lexema);
                $$=$1;
                if($<ident>2.info == NULL){
                    printf("EL CAMP INFO DE $2 es NULL\n");
                }else{
                    strcpy($<ident>$.lexema,$<ident>2.lexema);
                    if(($<ident>$.info -> lls != NULL)&&($<ident>2.info->lls != NULL)){
                        c3a_fusionar_list($<ident>$.info->lls,$<ident>2.info->lls);    
                    }else{
                        if($<ident>$.info -> lls == NULL){
                            if($<ident>2.info -> lls != NULL){
                                printf("LA LLISTA (lls) DE $1  ESTA MALAMENT\n");
                                $<ident>$.info -> lls = $<ident>2.info->lls;
                                printf("EL CAMP INFO $2 Fine =>> %s\n",$<ident>2.lexema);
                                printf("EL NUM D'elements es ==>> %i\n",$<ident>2.info->lls->num);
                            }else{
                                printf("LA LLISTA (lls) NO EXISTEIX A CAP DELS DOS\n");
                                $<ident>$.info -> lls = (Tlist *) calloc(1,sizeof(Tlist));
                            }
                        }else{
                            printf("LA LLISTA (lls) DE $2  ESTA MALAMENT\n");
                            
                        }

                    }
                }
            }
    }
;

expression_statement : ';' {fprintf(yyout,"GRAMATICA: %dL - expression_statement: ;   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| expression ';' {
        $$=$1;
    fprintf(yyout,"GRAMATICA: %dL - expression_statement: expression ;   <  %s\n",$<ident>1.line,$<ident>1.lexema);
        }
;

n_switch : /*buida*/ { N = (Tinfo *)calloc(1,sizeof(Tinfo)); 
					   N->test = c3a_get_quad(&cl);
					   c3a_emet_instr(&cl,"GOTO ");}

M : /*buida*/{$<ident>$.info = (Tinfo *)calloc(1,sizeof(Tinfo));
			  $<ident>$.info->quad = c3a_get_quad(&cl);
              strcpy($<ident>$.lexema,"M");
			  fprintf(yyout,"GRAMATICA: L - M STATUS!!!!!!!!!!!!!!!\n");
			  }
Q: /*buida*/ {
		$<ident>$.info = (Tinfo *)  calloc(1,sizeof(Tinfo));
		$<ident>$.info ->quad = c3a_get_quad(&cl);
		$<ident>$.lexema = (char *) calloc(2,sizeof(char));
		strcpy($<ident>$.lexema,"Q");
		fprintf(yyout,"GRAMATICA: L - Q STATUS!!!!!!!!!!!!!!!\n");
		c3a_emet_instr(&cl,"GOTO ");
		}
;

/*Aquesta regla es el que te el conflicte, afegint el "%prec THEN " conseguim eliminar-ho.*/
selection_statement : IF  '(' expression ')' M %prec  THEN statement  {
					  int num;
					  int linia;
					  int linia_f;
					  int i;

					  fprintf(yyout,"GRAMATICA: %dL - selection_statement: IF (expression) statement   <  %s (%s){%s }\n",$<ident>1.line,$<ident>1.lexema,$<ident>3.lexema,$<ident>6.lexema);  
					  if ($<ident>6.info == NULL){printf("El camp info es null\n");}

					  num = c3a_get_elements($<ident>3.info->llf);

					  for(i=0;i<num;i++)
						{
						 linia = c3a_get_elemAt($<ident>3.info->llf,i);
						 linia_f = c3a_get_elemAt($<ident>6.info->lls,c3a_get_elements($<ident>6.info->lls)-1);
   						 c3a_back_patching(&cl, linia,linia_f);
						} /*  aixo es llista seguent*/

					  num = c3a_get_elements($<ident>3.info->llc);

					  for(i=0;i<num;i++)
						{linia = c3a_get_elemAt($<ident>3.info->llc,i);
						 c3a_back_patching(&cl, linia,$<ident>6.info->quad);}
					  
					  $<ident>$.info = $<ident>6.info;
}
| IF  '(' expression ')' M %prec THEN statement ELSE Q statement {
					  int num;
					  int linia;
					  int linia_f;
					  int i;

				fprintf(yyout,"GRAMATICA: %dL - selection_statement: IF (expression) statement ELSE statement   <  %s ( %s ){%s} else{%s} \n",$<ident>1.line,$<ident>1.lexema,$<ident>3.lexema,$<ident>6.lexema,$<ident>9.lexema);
/*				printf("TENS CONT IF a: %i\n CONTING ELSE: %i\nSORTIDA %i\n",$<ident>6.info->quad,$<ident>9.info->quad,c3a_get_elemAt($<ident>9.info->lls,0));*/
				if($<ident>8.info == NULL){
					printf("ES NULLL!L!L!!LL!LL!L!LL!L!L\n");
				}
 					 num = c3a_get_elements($<ident>3.info->llf);

					  for(i=0;i<num;i++)
						{
						 linia = c3a_get_elemAt($<ident>3.info->llf,i);
						 linia_f = c3a_get_elemAt($<ident>6.info->lls,0); /***** ?????? NO TINDRIA QUE SER c3a_get_elements() en lloc de 0??*/
   						 c3a_back_patching(&cl, linia,linia_f+1);
						} /*  aixo es llista seguent*/

					  num = c3a_get_elements($<ident>3.info->llc);

					  for(i=0;i<num;i++)
						{linia = c3a_get_elemAt($<ident>3.info->llc,i);
						 c3a_back_patching(&cl, linia,$<ident>6.info->quad);}
					  
					  $<ident>$.info = $<ident>6.info;
					  c3a_back_patching(&cl,$<ident>8.info->quad,c3a_get_elemAt($<ident>9.info->lls,c3a_get_elements($<ident>9.info->lls)-1));
				}
| SWITCH '(' expression ')' n_switch statement {fprintf(yyout,"GRAMATICA: %dL - selection_statement: SWITCH (expresion) statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;


iteration_statement : WHILE '(' expression M ')' statement {
        fprintf(yyout,"GRAMATICA: %dL - iteration_statement: WHILE (expression) statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);
        char instr[MAX_C3A];
        int last_instr;

        printf(" ==> WHILE %s (%i)  {%s (%i)} \n",$<ident>3.lexema,$<ident>3.info->quad,$<ident>6.lexema,$<ident>6.info->quad);
        sprintf(instr,"GOTO %i",($<ident>3.info->quad)-1);
        c3a_emet_instr(&cl,instr);
        last_instr = c3a_get_quad(&cl);
        
        c3a_back_patching(&cl,$<ident>3.info->quad,$<ident>4.info->quad);
        c3a_back_patching(&cl,($<ident>3.info->quad)+1,last_instr);

        }
| DO statement WHILE '(' expression ')' ';' {fprintf(yyout,"GRAMATICA: %dL - iteration_statement: DO statement WHILE (expression)   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| FOR '(' expression ';' expression ';' expression Q ')' statement {
        fprintf(yyout,"GRAMATICA: %dL - iteration_statement: FOR (expression;expression;expression) statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);
        char instr[MAX_C3A];
        int last_instr;

        sprintf(instr,"GOTO %i",$<ident>7.info->quad);
        c3a_emet_instr(&cl,instr);
        last_instr = c3a_get_quad(&cl);

   		c3a_back_patching(&cl, $<ident>8.info->quad ,($<ident>5.info->quad)-1);
        c3a_back_patching(&cl, $<ident>5.info->quad ,($<ident>8.info->quad)+1);
        c3a_back_patching(&cl, ($<ident>5.info->quad)+1, last_instr);

    }
| FOR '(' ';' expression ';' expression Q')' statement {
        fprintf(yyout,"GRAMATICA: %dL - iteration_statement: FOR(;expression;expression) statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);
        char instr[MAX_C3A];
        int last_instr;

        sprintf(instr,"GOTO %i",$<ident>6.info->quad);
        c3a_emet_instr(&cl,instr);
        last_instr = c3a_get_quad(&cl);
   		c3a_back_patching(&cl, $<ident>7.info->quad ,($<ident>4.info->quad)-1);
        c3a_back_patching(&cl, $<ident>4.info->quad ,($<ident>7.info->quad)+1);
        c3a_back_patching(&cl, ($<ident>4.info->quad)+1, last_instr);

        }
| FOR '(' ';' ';' expression ')' statement{
        fprintf(yyout,"GRAMATICA: %dL - iteration_statement: FOR(;;expression) statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);
        char instr[MAX_C3A];
        int last_instr;

        sprintf(instr,"GOTO %i",$<ident>5.info->quad);
        c3a_emet_instr(&cl,instr);
        last_instr = c3a_get_quad(&cl);
       
        }
| FOR '(' ';' ';' ')' statement {
        fprintf(yyout,"GRAMATICA: %dL - iteration_statement: FOR(;;) statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);
        char instr[MAX_C3A];
        int last_instr;

        sprintf(instr,"GOTO %i",$<ident>6.info->quad);
        c3a_emet_instr(&cl,instr);
        last_instr = c3a_get_quad(&cl); 
        }
| FOR '(' expression ';' ';' expression ')' statement {
        fprintf(yyout,"GRAMATICA: %dL - iteration_statement: FOR(expression;;expression) statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);
        char instr[MAX_C3A];

        sprintf(instr,"GOTO %i",$<ident>6.info->quad);
        c3a_emet_instr(&cl,instr);
       
        }
| FOR '(' expression ';' ';' ')' statement {
        fprintf(yyout,"GRAMATICA: %dL - iteration_statement: FOR(expression;;) statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);
        char instr[MAX_C3A];

        sprintf(instr,"GOTO %i",$<ident>6.info->quad);
        c3a_emet_instr(&cl,instr);
 
        }
| FOR '(' ';' expression ';' ')' statement {
        fprintf(yyout,"GRAMATICA: %dL - iteration_statement: FOR(;expression;) statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);
        char instr[MAX_C3A];
        int last_instr;

        sprintf(instr,"GOTO %i",$<ident>4.info->quad);
        c3a_emet_instr(&cl,instr);
        last_instr = c3a_get_quad(&cl);
   		c3a_back_patching(&cl, $<ident>7.info->quad ,($<ident>4.info->quad)-1);
        c3a_back_patching(&cl, $<ident>4.info->quad ,($<ident>4.info->quad)+2);
        c3a_back_patching(&cl, ($<ident>4.info->quad)+1, last_instr);

        }
| FOR '(' expression ';' expression ';' ')' statement {
        fprintf(yyout,"GRAMATICA: %dL - iteration_statement: FOR(expression;expression;) statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);
        char instr[MAX_C3A];
        int last_instr;

        sprintf(instr,"GOTO %i",$<ident>5.info->quad);
        c3a_emet_instr(&cl,instr);
        last_instr = c3a_get_quad(&cl);
   		c3a_back_patching(&cl, $<ident>8.info->quad ,($<ident>5.info->quad)-1);
        c3a_back_patching(&cl, $<ident>5.info->quad ,($<ident>5.info->quad)+2);
        c3a_back_patching(&cl, ($<ident>5.info->quad)+1, last_instr);

       }
;

jump_statement : GOTO IDENTIFIER ';' {fprintf(yyout,"GRAMATICA: %dL - jump_statement: GOTO IDENTIFIER ;   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| CONTINUE ';' {fprintf(yyout,"GRAMATICA: %dL - jump_statement: CONTINUE;   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| BREAK ';' {fprintf(yyout,"GRAMATICA: %dL - jump_statement: BREAK;   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| RETURN ';' {
    fprintf(yyout,"GRAMATICA: %dL - jump_statement: RETURN;   <  %s\n",$<ident>1.line,$<ident>1.lexema);
    c3a_emet_instr(&cl,"RETURN");
    }
| RETURN expression ';' {
        char * instr;
		fprintf(yyout,"GRAMATICA: %dL - jump_statement: RETURN expression;  (%i) <  %s\n",$<ident>1.line,$<ident>2.type,$<ident>1.lexema); 
        instr =(char *) calloc((strlen($<ident>2.lexema)+8),sizeof(char));
        sprintf(instr,"RETURN %s",$<ident>2.lexema);
        c3a_emet_instr(&cl,instr);
		return_ctrl=1;
		$$=$2;
	}
;

translation_unit : external_declaration {fprintf(yyout,"GRAMATICA: %dL - translation_unit: external_declaration   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| translation_unit external_declaration {fprintf(yyout,"GRAMATICA: %dL - translation_unit: translation_unit external_declaration   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;

 /*DEFINICIONS DE FUNCIONS*/
 /*Per defecte passem el que ha de retornar, podriem passar el nom i el tipus a retornar millor*/
external_declaration : function_definition {
		fprintf(yyout,"GRAMATICA: %dL - external_declaration: function_definition   <  %s\n",$<ident>1.line,$<ident>1.lexema);
		ba_sortir_ambit();
		pop_ambit($<ident>1.lexema);
		}
| declaration {fprintf(yyout,"GRAMATICA: %dL - external_declaration: declaration   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;

function_definition : declarator compound_statement {
			fprintf(yyout,"GRAMATICA: %dL - unction_definition: declarator compound_statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	}
| declaration_specifiers declarator declaration_list compound_statement {
			fprintf(yyout,"GRAMATICA: %dL - function_definition: declaration_specifiers declarator declaration_list compound_statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);
	}
| declaration_specifiers declarator compound_statement {
		fprintf(yyout,"GRAMATICA: %dL - function_definition: declaration_specifiers declarator compound_statement   <  %s\n",$<ident>1.line,$<ident>2.lexema);
		if ($<ident>2.type != VOID){
			if(return_ctrl==1){
				comprova_tipus_return($<ident>2.type, $<ident>3.type,$<ident>3.line);
				return_ctrl=0;
			}else{
				fprintf(yyout,"SEMANTICA: %dL - ERROR: Falta retornar un valor de tipus %s\n",$<ident>3.line,$<ident>1.lexema);
				fprintf(stderr,"SEMANTICA: %dL - ERROR: Falta retornar un valor de tipus %s\n",$<ident>3.line,$<ident>1.lexema);
			}
		}else{
			if(return_ctrl==1){
				fprintf(yyout,"SEMANTICA: %dL - ERROR: No es te que retornar, tot així retornes un tipus %d\n",$<ident>3.line,$<ident>3.type);
				fprintf(stderr,"SEMANTICA: %dL - ERROR: No es te que retornar, tot així retornes un tipus %d\n",$<ident>3.line,$<ident>3.type);
				return_ctrl=0;
			}
		}
		$$=$2;
		$<ident>$.type=$<ident>1.type;
	}
| declarator declaration_list compound_statement {fprintf(yyout,"GRAMATICA: %dL - function_definition: declarator delclaration_list compound_statement   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;

declaration_list : declaration {fprintf(yyout,"GRAMATICA: %dL - declaration_list: declaration   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
| declaration_list declaration {fprintf(yyout,"GRAMATICA: %dL - declaration_list: declaration_list declaration   <  %s\n",$<ident>1.line,$<ident>1.lexema);}
;


%%

int init_analisi_sintactic(char* filename){

    int error = EXIT_SUCCESS;
    char * name = (char *) calloc(strlen(filename)+7, (sizeof(char)));
    name_c3a = (char *) calloc(strlen(filename)+5, (sizeof(char)));
    name_ba = (char *) calloc(strlen(filename)+4, (sizeof(char)));


    sprintf(name,"%s.debug",filename);
    sprintf(name_c3a,"%s.c3a",filename);
    sprintf(name_ba,"%s.ra",filename);
    yyout = fopen(name,"w");

    if (yyout == NULL){

    error = EXIT_FAILURE;

}

return error;

}

int analisi_semantic(){
int error;

 if (yyparse() == 0)
 {
 error =  EXIT_SUCCESS;
 } else {
 error =  EXIT_FAILURE;
 }

 return error;
}

int end_analisi_sintactic(){

int error;

error = fclose(yyout);

if(error == 0){
 error = EXIT_SUCCESS;
}else{
 error = EXIT_FAILURE;
}

return error;

}

void yyerror(char *explanation){
fprintf(stderr,"Error: %s ,in line %d \n",explanation,yylineno);
exit(1);
}


/*Tractament d'errors de la taula de simbols SYMTAB*/
void error_taula_simbols(int codi,const char *lexema)
{ switch (codi){
	
	case SYMTAB_NO_MEMORY:	fprintf(stderr, "Error de gestio de la taula de simbols. Memoria insuficient no es pot crear l'entrada per a l'identificador %s !!! \n", lexema);
				break;

	case SYMTAB_DUPLICATE:	fprintf(stderr, "Error de gestio de la taula de simbols. L'entrada a la taula per a l'identificador %s ja existeix !!! \n", lexema);
				break;

	case SYMTAB_NOT_FOUND:	fprintf(stderr, "Error de gestio de la taula de simbols. L'entrada a la taula per a l'identificador %s no existeix !!! \n", lexema);
				break;

	case SYMTAB_STACK_OVERFLOW:	fprintf(stderr, "Error de gestio de la taula de simbols. No es pot crear el nou ambit per al subprograma %s !!! \n",lexema);
				break;

	case SYMTAB_STACK_UNDERFLOW:	fprintf(stderr, "Error de gestio de la taula de simbols. No es pot desapilar l'ambit global %s !!! \n",lexema);
				break;

	case SYMTAB_NOT_TOP:	fprintf(stderr, "Error de gestio de la taula de simbols. No es permet desapilar l'ambit %s encara no tancat !!! \n",lexema);
				break;
	}
}
